Via Conque I use vim as an IDE for all my coding. I am starting to work in python, which is persnickety about spacing, so to test deeply indented subroutines or code blocks, I need to gate code sent to the terminal with %cpaste and --. That is, if I am interactively editing and testing the following:

def wait_job(layer2, vault_name, job_id, sleepsec=60, timeout=86400):
    """ Wait for a job to terminate. """
    t0 = datetime.now()
    vault = fetch_vault(layer2, vault_name)
    while 1:
        job = vault.get_job(job_id)
        if not job.completed:
            tf = datetime.now()
            delta = tf - t0
            if (delta.seconds > timeout):
                # 2FIX: should this just return false?
                raise Exception('timed out')
    wasok = job.completed
    return wasok

And grab the code block starting from if not job.completed, and send it to an ipython process in a Conque window, I have to send:

        if not job.completed:
            tf = datetime.now()
            delta = tf - t0
            if (delta.seconds > timeout):
                # 2FIX: should this just return false?
                raise Exception('timed out')

I believe I have to modify the following line in the definition of ConqueTerm_SendVisKey:

if maparg(g:ConqueTerm_SendVisKey, 'v') == ''
  sil exe 'v' . map_modifier . 'map <silent> ' . g:ConqueTerm_SendVisKey . ' :<C-u>call conque_term#send_selected(visualmode())<CR>'

But am not sure where to start. Probably it would be better to define variables for gate start and gate end, but can I just do a string concat around visualmode()? Or must I send call the send three times?

  • Not sure I understood your question because I know nothing about python, Conque or IPython. So I'm going to try and reformulate it with my words. You've got a key whose value is stored in the global variable g:ConqueTerm_SendVisKey, let's say <F9>. When you visually select some text and hit on this key, it's sent to some other process, which is what you want. But sometimes you want to send something slightly different: %cpaste + visually selected text + --. Is it what you want? – saginaw Jan 25 '16 at 19:38
  • @saginaw that is it exactly; since I use <F9> everywhere, I would prefer to set a text prefix and suffix (empty by default) which are always added to the payload, and then set them by filetype. I admit, however, I don't even know how to do basic string concatenation or interpolation in vimscript. – shabbychef Jan 25 '16 at 20:28
  • Not sure, but you could try this. In your vimrc add this autocmd: autocmd BufNewFile,BufRead * if &ft ==# 'python' | let [b:gate_start, b:gate_end] = ["%cpaste\n", "\n--"] | else | let [b:gate_start, b:gate_end] = ["", ""] | endif It will set the value for the prefix/suffix. Next, in the code of the send_selected() function inside your Conque plugin, there must be a line like this: sil exe "normal! `<" . a:type . "`>y" This line copies your visually selected text which is now inside the unnamed register @@. – saginaw Jan 25 '16 at 20:56
  • Just after this line, you could try to add the following line, which hopefully will do the concatenation: let @@ = b:gate_start . @@ . b:gate_end – saginaw Jan 25 '16 at 20:57
  • Assuming you're using this Conque plugin (github.com/vim-scripts/Conque-Shell), here is the line after which you must do the concatenation: github.com/vim-scripts/Conque-Shell/blob/master/autoload/… – saginaw Jan 25 '16 at 21:24

It's possible to get this behaviour without changing ConqueTerm's code itself. The code below applies your desired behaviour to linewise visual mode selections*.

It works by adding the gates to the buffer, sending the whole lot over to ConqueTerm (using the same code that ConqueTerm itself uses in its mapping), and then removing the gates again.

You can add the code to your .vimrc, or if you want it only to apply to Python files, you could add <buffer> to the vnoremap mapping to make it buffer-specific and put it in .vim/after/ftplugin/markdown.vim so it applies to all Python files:

vnoremap <silent> <f9> :<c-u>call ConqueWrapper("%cpaste", "--")<CR>

function! ConqueWrapper(start_gate, end_gate)
  let m = visualmode()

  " Only apply this wrapper to linewise selections
  if m ==# 'V'
    let start_line = line("'<")
    let end_line = line("'>")

    " Add in the code gates
    call append(end_line, a:end_gate)
    call append(start_line - 1, a:start_gate)

    " Reset the visual marks
    call setpos("'<", [0, start_line, 0, 0])
    call setpos("'>", [0, end_line + 2, 0, 0])

    " Send to ConqueTerm
    call conque_term#send_selected("V")

    " Switch back to original buffer
    wincmd p

    " Remove the code gates
    execute end_line + 2 . "delete _"
    execute start_line . "delete _"

    " Switch back to ConqueTerm
    wincmd p
    " Not linewise: just pass it on directly to ConqueTerm
    execute "call conque_term#send_selected(\"" . m . "\")"

My personal preference is not to make changes to the source code of plugins if I can avoid it, because then you have to either:

  1. Make a fork of plugin project, and keep this updated by merging in future changes from the original project,
  2. Or reapply your changes every time you update the plugin.

...neither of which is a very appealing prospect.

* Because I don't think it makes much sense for characterwise or blockwise selections, and the code to implement it would be more complicated, and therefore harder for you to understand.


Unfortunately, I'm not sure I fully understand the problem you are having or what you are trying to achieve. From what I can gather, you're trying to interactively execute python code from vim. If you're willing to entertain non-Conque related solutions, then I'd highly recommend the vim-ipython plugin. It allows you to select arbitrary lines of python code and execute them in an existing ipython session. I believe it is fairly forgiving about the indentation as long as the selected block is correctly indented within itself. This should allow you to select just the if block within a function and execute it even though it may be indented a few levels relative to the rest of the file (hopefully that made sense).

The plugin can be found here: https://github.com/ivanov/vim-ipython

  • thanks for the tip, but I use Conque ubiquitously for dev work in many languages (R, matlab, bash, MySQL, etc) and am hoping to avoid context switching for the sake of one language. – shabbychef Jan 25 '16 at 19:16
  • The problem to be solved as I see it is to modify the maparg ... sil exe bits (and vimscript is Greek to me) to accept an optional prefix and postfix (which I can define based on filetype) that would contain the gate strings viz %cpaste and so on. – shabbychef Jan 25 '16 at 19:20
  • @shabbychef The line you're referring to simply defines a mapping. The mapping tells Vim that whenever you hit on <F9> in visual mode, it must call the function send_selected(). So you must not modify the mapping but the function which is defined here: github.com/vim-scripts/Conque-Shell/blob/master/autoload/… The line 1227 copies your visual selection in the unnamed register @@. You can concatenate your variables gate_start and gate_end just after it. – saginaw Jan 25 '16 at 21:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.