Setting multiple values for Vim command -complete attribute - shell

I am trying to enable command completion for a custom command that I am setting up for a plugin in the following manner:
command! -complete=shellcmd -nargs=* EScratch call s:ShellScratch(<f-args>)
I would like to enable complete options for shellcmd and file. However it seems that the complete attribute would only take 1 option.
To give a bit more context as to what I am trying to achieve: I am working on a plugin to create a simple scratch buffer. I would like to be able to run a shell command from the command mode and copy the output to the scratch buffer. I have been able to achieve all this but it would be much more productive to have auto completion similar to shell. The complete script can be viewed here https://github.com/ifthikhan/vimscratch/blob/master/plugin/vimscratch.vim. Any pointers will be highly appreciated.

Unfortunately, you can't. If you really need this, you have to either
define two separate commands, e.g. :ScratchShell and :ScratchFile, with the corresponding completions, or
use a -complete=custom[list] and provide your own complete function, where you have to re-implement both sources yourself. Filename completion actually is quite easily done with glob(); I'm not so sure about shell commands.

Related

Refreshing Bash prompt after invocation of a readline bound command

My shell is GNU Bash 4.3.11, and I currently have M-h bound to cd .. by calling the builtin
bind -x '"\eh": "cd .."'
This gives me a nifty way to navigate up the directory tree, as I can repeatedly hit M-h instead of the incredibly time-consuming cd ... It has the downside, however, either of not resetting my $PS1 or of not redrawing my prompt, so I lose the context of my current working directory until I enter a new command.
One alternative I'm aware of is to put a macro like
"\eh": "\C-a\C-kcd ..\C-m"
in my .inputrc directly. This, however, has the downside of not only losing the context of any existing command I'm typing in (which I think can probably be worked around) but also of printing out cd .. (which I don't think can be).
My desired behavior is to be able to be in a directory ~/one/two with prompt ~/one/two$; hit M-h; and then be in ~/one and have the prompt be ~/one$, ideally keeping any command I had initially. How can I achieve this?
Figured this out.
# maintain state
bind -x '"\200": TEMP_LINE=$READLINE_LINE; TEMP_POINT=$READLINE_POINT'
bind -x '"\201": READLINE_LINE=$TEMP_LINE; READLINE_POINT=$TEMP_POINT; unset TEMP_POINT; unset TEMP_LINE'
# "cd .." use case.
bind -x '"\206": "cd .."'
bind '"\eh":"\200\C-a\C-k\206\C-m\201"'
I'm quite late to that party - and came here looking for that answer also. First of all: As you were the only one providing information on this: thanks for not letting it come to this: https://xkcd.com/979/ ;) instead you pointed me to the on corner in that fractal that seems to hold a solution.
This approach, in my opinion backed up by hours of trying, is the only one where you can a) replace content on the line, and b) execute bash code. Let me offer up some more suggestions to a specific problem:
If you are trying to have it both ways: insert something on the command line, or executing code, things can get very tricky. for both, there exist bindings, and I let the reader figure out things with help bind. But in the case you e.g. have FZF produce some directory as output, and you'd either cd to it, or have it pasted into your command -- depending on the keystroke done in FZF -- things will get near impossible. you'll face either the not-updated-promt problem, or not be able to execute the cd command in the top shell (where it has effect).
Your solution would be a multiplexing -x binding, inspecting the output for "macros" (get extracted and eval'd) or the default pass-through (manipulating READLINE_LINE/POINT).
Because the solution has some enormity, and the audience may be limited (closed answer...), I'll leave it at a haphazard gist where I pasted my code which works now. To make up for the brevity and uncommented-ness, I welcome any questions in comment or elsewhere. Hope someone may be pointed in the right direction.
- The code related to this question starts in function bindInsertEvalWithMacrosVi
- It is designed for Vi keybindings but the same principles apply for normal readline mode
- It depends on some \C-x\C-... combinations to do redrawing in places that are not related to this post.
https://gist.github.com/simlei/032470cfcd23641987f97a96749128d7

ksh - Display Current Mode

Is there any way to have ksh display the current typing mode at the bottom of the window like vim; like "Insert", "Command", "Visual", etc? Unfortunately, I am having a lot of trouble remembering which mode I'm in and find the shell unintuitive (at least until I get used to all the commands). I consistantly hit the wrong key in command mode and have difficulty figuring out how to get back to proper typing (sometimes it lets me type but not delete part of the line and I don't know why).
I am required to use ksh for work and am heavily restricted in what I can download and install, but I need to figure this out. Hopefully there is something I can do with a profile or script along these lines to help ease the transistion. Also, this is HP-Unix, in case that affects anything.
This set -o alone command will show if emacs is defined to on
$ set -o|grep emacs
emacs on

Adding Helper Methods to Mongo Shell

Is there any way of adding "helper" methods to the mongo shell that loads each time you use it?
Basically whenever you want to query by _id, you have to do something like this.
db.collectionName.findOne({_id: ObjectId('THIS-IS-AN-OBJECTID')})
Whenever I'm going to be doing a lot of command line commands, I alias the ObjectId function to make it easier to type.
var ob = ObjectId;
db.collectionName.findOne({_id: ob('AN-OBJECTID')})
db.collectionName.findOne({_id: ob('ANOTHER-ONE')})
db.collectionName.findOne({_id: ob('ANOTHER')})
It would be pretty chill if there was a way of either running a specified piece of JS / add a chunk of code that runs each time mongo is pulled up from the shell. I checked out MongoDB's CLI documentation, but didn't see anything like that available, so I figured I would ask here.
I know there is a possibility of using this nefariously, so this might be a situation where it might be unsupported by the mongo shell by default. This might be a situation where we can create a helper bash script of some sort to launch the shell, then inject keyboard input to create the helper ob function? Not sure how this could be tackled personally, but would love some insight on how to do something like this, either natively or through a helper script of some sort.
If you want code to execute every time you launch the shell, then whatever you place in .mongorc.js will be run on launch:
.mongorc.js File
When starting, mongo checks the user’s HOME directory for a JavaScript file named .mongorc.js. If found, mongo interprets the content of .mongorc.js before displaying the prompt for the first time. If you use the shell to evaluate a JavaScript file or expression, either by using the --eval option on the command line or by specifying a .js file to mongo, mongo will read the .mongorc.js file after the JavaScript has finished processing. You can prevent .mongorc.js from being loaded by using the --norc option.
So simply define your variable association there.
You could also supply a file of your choice along with the --shell option to let the command know you want the shell opened on completion of any instructions contained:
mongo --shell file_with_javascript.js
But as mentioned, the .mongorc.js file would still be called (if present) unless the --norc option was also specified.

What exactly is going on in Proc::Background?

I am trying to write a script that automates other perl scripts. Essentially, I have a few scripts that rollup data for me and need to be run weekly. I also have a couple that need to be run on the weekend to check things and email me if there is a problem. I have the email worked out and everything but the automation. Judging by an internet search, it seems as though using Proc::Background is the way to go. I tried writing a very basic script to test it and can't quite figure it out. I am pretty new to Perl and have never automated anything before (other than through windows task scheduler), so I really don't understand what the code is saying.
My code:
use Proc::Background;
$command = "C:/strawberry/runDir/SendMail.pl";
my $proc1 = Proc::Background -> new($command);
I receive an error that says no executable program located at C:... Can someone explain to me what exactly the code (Proc::Background) is doing? I will then at least have a better idea of how to accomplish my task and debug in the future. Thanks.
I did notice on Proc::Background's documentation the following:
The Win32::Process module is always used to spawn background processes
on the Win32 platform. This module always takes a single string
argument containing the executable's name and any option arguments.
In addition, it requires that the absolute path to the executable is
also passed to it. If only a single argument is passed to new, then
it is split on whitespace into an array and the first element of the
split array is used at the executable's name. If multiple arguments
are passed to new, then the first element is used as the executable's
name.
So, it looks like it requires an executable, which a Perl script would not be, but "perl.exe" would be.
I typically specify the "perl.exe" in my Windows tasks as well:
C:\dwimperl\perl\bin\perl.exe "C:\Dropbox\Programming\Perl\mccabe.pl"

Extending tcsh completion

I must work with tcsh.
I am using an internal tool that provides basic completion for some of its commands.
I would like to extend the completion.
I mean that in future releases the default completion may evolve.
I tried something like this:
set def_cmpl = complete tool
complete tool $def_cmpl 'n/-l/(reg short long gui)/'
But I don't understand the result I get.
Indeed, the quotes inside $def_cmpl are doubled:
tcsh> complete tool
''n#-t#$script#'' n/-l/(reg short long gui)/'
I tried some tricks with echo, sed, etc. but I can't avoid those ''.
Could somebody help me?
Please don't say go on bash... The tool doesn't support it...
Finally, I did not find a solution to keep the data inside the script. So, the solution was to redirect the output of the complete command inside a file and then to append new lines to the file.

Resources