How to test external tab completion script in Ruby - 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.

Related

How to extract information from a command prompt using shell script?

I need a shell script using which I can fetch data from command prompt. I need to fetch data from the command prompt of a router. When I write commands in a shell script it goes the prompt but not executing the next command. So running the script just stuck in the prompt. Bellow is my script file
#!/bin/sh
ccli
rsc
where ccli is the command to enter the prompt and rsc is the command to fetch some infomation.
So please suggest some method.
If ccli reads commands from stdin (which I don't know), you might get further with
printf 'rsc\n' | ccli
For more complicated tasks I suggest you look into expect which was invented for the sole reason of driving interactive programs in a scripted way.

Running shell commands in GVim without echoing the Vim command

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.

How to modify every bash command before execution?

Is there a way to modify every command that is entered at the bash prompt with a script/hook?
In my ideal world, the script would fire after the user has entered the command but BEFORE the Enter key is pressed. It would get the command string as a parameter, modifiy it and hand it over to bash for executing (so everything would happen transparently).
I would use this hook for some company-specific substitutions which cannot be done using aliases, but above all I'm interested if this can be done.
I know of some hacks to do something with the last command after it has been executed (trap 'function' DEBUG and the like) as there are a lot of questions concerning that scenario but this is of no help here.
Thanks and kind regards!
What you want is a kind of command completion -- it seems to me.
There is a lot behind bash line editing: bindable readline commands, or command completion and command substitution.
First off you can write write and compile your own bash builtins:
http://www.drdobbs.com/shell-corner-bash-dynamically-loadable-b/199102950
Next, you can alter bash through what people call edit line or readline:
Start here maybe:
http://www.math.utah.edu/docs/info/features_7.html
http://www.gnu.org/software/bash/manual/html_node/Command-Line-Editing.html

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.

How to call bash commands from tcl script?

Bash commands are available from an interactive tclsh session. E.g. in a tclsh session you can have
% ls
instead of
$ exec ls
However, you cant have a tcl script which calls bash commands directly (i.e. without exec).
How can I make tclsh to recognize bash commands while interpreting tcl script files, just like it does in an interactive session?
I guess there is some tcl package (or something like that), which is being loaded automatically while launching an interactive session to support direct calls of bash commans. How can I load it manually in tcl script files?
If you want to have specific utilities available in your scripts, write bridging procedures:
proc ls args {
exec {*}[auto_execok ls] {*}$args
}
That will even work (with obvious adaptation) for most shell builtins or on Windows. (To be fair, you usually don't want to use an external ls; the internal glob command usually suffices, sometimes with extra help from some file subcommands.) Some commands need a little more work (e.g., redirecting input so it comes from the terminal, with an extra <#stdin or </dev/tty; that's needed for stty on some platforms) but that works reasonably well.
However, if what you're asking for is to have arbitrary execution of external programs without any extra code to mark that they are external, that's considered to be against the ethos of Tcl. The issue is that it makes the code quite a lot harder to maintain; it's not obvious that you're doing an expensive call-out instead of using something (relatively) cheap that's internal. Putting in the exec in that case isn't that onerous…
What's going on here is that the unknown proc is getting invoked when you type a command like ls, because that's not an existing tcl command, and by default, that command will check that if the command was invoked from an interactive session and from the top-level (not indirectly in a proc body) and it's checking to see if the proc name exists somewhere on the path. You can get something like this by writing your own proc unknown.
For a good start on this, examine the output of
info body unknown
One thing you should know is that ls is not a Bash command. It's a standalone utility. The clue for how tclsh runs such utilities is right there in its name - sh means "shell". So it's the rough equivalent to Bash in that Bash is also a shell. Tcl != tclsh so you have to use exec.

Resources