3

new VIM user. I'm trying to make creating python properties easier for my class definitions. What I would like for say I type

:pyp x

then VIM will autofill where my cursor is

@property
def x(self):
   return self.x
@property.setter
   def x(self,val):
      self._x = val

or more abstractly I type

:pyp <property_name>

and VIM fills

@property
def <property_name>(self):
   return self.<property_name>
@property.setter
   def <property_name>(self,val):
      self._<property_name> = val

I've looked at a few posts and the wikis on functions, macros but I'm very unsure of how to go about it or what to even look up as I am brand new VIM user, less than a week old.

I tried using [this][1] as an example, in my .vimrc but I couldn't even get that to work.

Edit:

So the code I am currently trying is

function! PythonProperty(prop_name)
 let cur_line = line('.')
 let num_spaces = indent('.')
 let spaces = repeat(' ',num_spaces)
 let lines = [ spaces."@property",
             \ spaces."def ".prop_name."(self):",
             \ spaces."   return self.".property,
             \ spaces."@property.setter",
             \ spaces."def".prop_name."(self,val)",
             \ spaces."   self._".prop_name." = val" ]
 call append(cur_line,lines)
endfunction

and I am getting the errors

E121: Undefined variable: prop_name

I am typing
`:call PythonProperty("x")`

  [1]: https://vi.stackexchange.com/questions/9644/how-to-use-a-variable-in-the-expression-of-a-normal-command
Melendowski
  • 404
  • 4
  • 16
  • there are plugins for code generation from some template. like snippet, neosnippet... you can define the template – Kent Jul 17 '19 at 11:25
  • 1
    @Kent Yeah, the system I am working on, its very very difficult if not impossible to get pluggins so I have to do stuff through my vimrc or other method. Basically trying to get a plugin installed could take half a year. – Melendowski Jul 17 '19 at 11:26
  • you could ask it in [vim exchange](https://vi.stackexchange.com/) – Tomerikoo Jul 17 '19 at 11:42
  • @MathWannaBe456 you can install vim plugins in your home directory, it is user-specific stuff. – Kent Jul 17 '19 at 12:06
  • Possible duplicate of [Writing a vim function to insert a block of static text](https://stackoverflow.com/questions/690386/writing-a-vim-function-to-insert-a-block-of-static-text) – phd Jul 17 '19 at 12:26
  • https://stackoverflow.com/search?q=%5Bvim%5D+insert+text+argument – phd Jul 17 '19 at 12:27
  • https://stackoverflow.com/q/52254413/7976758 – phd Jul 17 '19 at 12:27
  • @Kent we don't have internet on this particular system. it is completely locked down and nothing can be installed anywhere without admin priv – Melendowski Jul 17 '19 at 12:44
  • @MathWannaBe456 you cant clone a git repo to a USB on another system and copy it over? – D. Ben Knoble Jul 17 '19 at 13:14
  • @D.BenKnoble No we aren't allowed storage devices in the building – Melendowski Jul 17 '19 at 13:14

1 Answers1

4

E121: Undefined variable: prop_name

In VimScript variables have scopes. The scope for function arguments is a:, while the default inside a function is l: (local variable). So the error means that l:prop_name was not yet defined.

Now how I do this:

function! s:insert_pyp(property)
    let l:indent = repeat(' ', indent('.'))
    let l:text = [
        \ '@property',
        \ 'def <TMPL>(self):',
        \ '    return self.<TMPL>',
        \ '@property.setter',
        \ '    def <TMPL>(self,val):',
        \ '        self._<TMPL> = val'
    \ ]
    call map(l:text, {k, v -> l:indent . substitute(v, '\C<TMPL>', a:property, 'g')})
    call append('.', l:text)
endfunction

command! -nargs=1 Pyp :call <SID>insert_pyp(<q-args>)

Alternatively, we can simulate actual key presses (note that we don't need to put indents in the template anymore; hopefully, the current buffer has set ft=python):

function! s:insert_pyp2(property)
    let l:text = [
        \ '@property',
        \ 'def <TMPL>(self):',
        \ 'return self.<TMPL>',
        \ '@property.setter',
        \ 'def <TMPL>(self,val):',
        \ 'self._<TMPL> = val'
    \ ]
    execute "normal! o" . substitute(join(l:text, "\n"), '\C<TMPL>', a:property, 'g') . "\<Esc>"
endfunction

command! -nargs=1 Pyp2 :call <SID>insert_pyp2(<q-args>)

its very very difficult if not impossible to get pluggins

I suggest you to watch this video on youtube. In fact, many of Vim plugins are just overkill.

Matt
  • 13,674
  • 1
  • 18
  • 27
  • I'm getting error `E121 Undefined variable: k` It does however spit out the template though – Melendowski Jul 17 '19 at 15:42
  • 1
    @MathWannaBe456 Not sure why so, I have none. Maybe buggy Vim version? Try old syntax for `map()` (without lambda), or even plain `for i in range(len(l:text))`. – Matt Jul 17 '19 at 15:49
  • Yeah im totally confused on why it isnt working. I read up on the map with lambda, key-val thing and it seems like it should be working – Melendowski Jul 17 '19 at 16:22
  • Is this how you would do it with the for loop? `for i in range(len(l:text))` `l:text[i] = l:indent . substitute(l:text[i], '\C', a:property, 'g')` `endfor` – Melendowski Jul 17 '19 at 16:44
  • 1
    @MathWannaBe456 Yes, except you forgot 'let'. – Matt Jul 17 '19 at 16:47