Loading ...
Sorry, an error occurred while loading the content.
 

Error in ftplugin/changelog.vim

Expand Messages
  • Josh Stone
    Hi, I get the following error when trying to use the global o mapping from ftplugin/changelog.vim: Error detected while processing function
    Message 1 of 4 , Dec 12, 2013
      Hi,

      I get the following error when trying to use the global <Leader>o mapping from ftplugin/changelog.vim:

      Error detected while processing function <SNR>13_open_changelog:
      line 46:
      E118: Too many arguments for function: <SNR>13_new_changelog_entry

      That's the last line in open_changelog:

      call s:new_changelog_entry(prefix)
      endfunction

      And indeed it doesn't look like it should have arguments:

      " Internal function to create a new entry in the ChangeLog.
      function! s:new_changelog_entry()

      Browsing source history, this function dropped "(...)" arguments in the 2011-05-02 revision, but I can't see that arguments were even used before that.

      So the global <Leader>o mapping only succeeds to open the ChangeLog after the error message. From there I can use the local <Leader>o, at least.

      The plugin code seems plainly wrong to me, but I'm open to suggestions if someone can see that I'm doing something wrong...

      Thanks,
      Josh

      --
      --
      You received this message from the "vim_use" maillist.
      Do not top-post! Type your reply below the text you are replying to.
      For more information, visit http://www.vim.org/maillist.php

      ---
      You received this message because you are subscribed to the Google Groups "vim_use" group.
      To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@....
      For more options, visit https://groups.google.com/groups/opt_out.
    • Tony Mechelynck
      ... Indeed, AFAICT, before the change any number of arguments could be passed but they wouldn t be used. This seems weird but there might be reasons for it.
      Message 2 of 4 , Dec 12, 2013
        On 13/12/13 03:02, Josh Stone wrote:
        > Hi,
        >
        > I get the following error when trying to use the global <Leader>o mapping from ftplugin/changelog.vim:
        >
        > Error detected while processing function <SNR>13_open_changelog:
        > line 46:
        > E118: Too many arguments for function: <SNR>13_new_changelog_entry
        >
        > That's the last line in open_changelog:
        >
        > call s:new_changelog_entry(prefix)
        > endfunction
        >
        > And indeed it doesn't look like it should have arguments:
        >
        > " Internal function to create a new entry in the ChangeLog.
        > function! s:new_changelog_entry()
        >
        > Browsing source history, this function dropped "(...)" arguments in the 2011-05-02 revision, but I can't see that arguments were even used before that.
        >
        > So the global <Leader>o mapping only succeeds to open the ChangeLog after the error message. From there I can use the local <Leader>o, at least.
        >
        > The plugin code seems plainly wrong to me, but I'm open to suggestions if someone can see that I'm doing something wrong...
        >
        > Thanks,
        > Josh
        >

        Indeed, AFAICT, before the change any number of arguments could be
        passed but they wouldn't be used. This seems weird but there might be
        reasons for it. For instance avoiding the error in s:open_changelog
        without fixing it. Doesn't look very convincing to me.

        The following is the output from some detective work I did on my hg
        clone. Warning! It is bulky. You may want to skip it. Only my sig is
        after it.

        Here's the hg log (where 2897 is the ordinal on my clone and may be
        different from Bram's; the CSID in hex is of course the same in both):

        > changeset: 2897:3c7da93eb7f9
        > user: Bram Moolenaar <bram@...>
        > date: Tue May 10 17:18:44 2011 +0200
        > files: runtime/doc/change.txt runtime/doc/eval.txt runtime/doc/fold.txt runtime/doc/if_pyth.txt runtime/doc/map.txt runtime/doc/message.txt runtime/doc/options.txt runtime/doc/syntax.txt runtime/doc/tags runtime/doc/todo.txt runtime/ftplugin/changelog.vim runtime/syntax/hostsaccess.vim runtime/syntax/php.vim runtime/syntax/readline.vim runtime/syntax/sysctl.vim
        > description:
        > Updated runtime files.
        >
        >

        so the change was made official on May 10.

        Here's the hg diff of that file for that change (with 8 lines of context
        which is what I normally use):

        > diff --git a/runtime/ftplugin/changelog.vim b/runtime/ftplugin/changelog.vim
        > --- a/runtime/ftplugin/changelog.vim
        > +++ b/runtime/ftplugin/changelog.vim
        > @@ -1,12 +1,12 @@
        > " Vim filetype plugin file
        > " Language: generic Changelog file
        > " Maintainer: Nikolai Weibull <now@...>
        > -" Latest Revision: 2010-08-17
        > +" Latest Revision: 2011-05-02
        > " Variables:
        > " g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) -
        > " description: the timeformat used in ChangeLog entries.
        > " default: "%Y-%m-%d".
        > " g:changelog_dateformat -
        > " description: the format sent to strftime() to generate a date string.
        > " default: "%Y-%m-%d".
        > " g:changelog_username -
        > @@ -94,18 +94,19 @@ if &filetype == 'changelog'
        > endif
        > endfor
        > return ""
        > endfunction
        >
        > function! s:try_reading_file(path)
        > try
        > return readfile(a:path)
        > + catch
        > + return []
        > endtry
        > - return []
        > endfunction
        >
        > function! s:passwd_field(line, field)
        > let fields = split(a:line, ':', 1)
        > if len(fields) < field
        > return ""
        > endif
        > return fields[field - 1]
        > @@ -165,25 +166,25 @@ if &filetype == 'changelog'
        > let line = getline(lnum)
        > let cursor = stridx(line, '{cursor}')
        > call setline(lnum, substitute(line, '{cursor}', '', ''))
        > endif
        > startinsert!
        > endfunction
        >
        > " Internal function to create a new entry in the ChangeLog.
        > - function! s:new_changelog_entry(...)
        > + function! s:new_changelog_entry()
        > " Deal with 'paste' option.
        > let save_paste = &paste
        > let &paste = 1
        > call cursor(1, 1)
        > " Look for an entry for today by our user.
        > let date = strftime(g:changelog_dateformat)
        > let search = s:substitute_items(g:changelog_date_entry_search, date,
        > - \ g:changelog_username)
        > + \ s:username())
        > if search(search) > 0
        > " Ok, now we look for the end of the date entry, and add an entry.
        > call cursor(nextnonblank(line('.') + 1), 1)
        > if search(g:changelog_date_end_entry_search, 'W') > 0
        > let p = (line('.') == line('$')) ? line('.') : line('.') - 1
        > else
        > let p = line('.')
        > endif
        > @@ -192,17 +193,17 @@ if &filetype == 'changelog'
        > call append(p, ls)
        > call cursor(p + 1, 1)
        > else
        > " Flag for removing empty lines at end of new ChangeLogs.
        > let remove_empty = line('$') == 1
        >
        > " No entry today, so create a date-user header and insert an entry.
        > let todays_entry = s:substitute_items(g:changelog_new_date_format,
        > - \ date, g:changelog_username)
        > + \ date, s:username())
        > " Make sure we have a cursor positioning.
        > if stridx(todays_entry, '{cursor}') == -1
        > let todays_entry = todays_entry . '{cursor}'
        > endif
        >
        > " Now do the work.
        > call append(0, split(todays_entry, '\n'))
        >

        And here's (as a diff from "before the file existed") how it was before
        the change:

        > diff --git a/runtime/ftplugin/changelog.vim b/runtime/ftplugin/changelog.vim
        > new file mode 100644
        > --- /dev/null
        > +++ b/runtime/ftplugin/changelog.vim
        > @@ -0,0 +1,301 @@
        > +" Vim filetype plugin file
        > +" Language: generic Changelog file
        > +" Maintainer: Nikolai Weibull <now@...>
        > +" Latest Revision: 2010-08-17
        > +" Variables:
        > +" g:changelog_timeformat (deprecated: use g:changelog_dateformat instead) -
        > +" description: the timeformat used in ChangeLog entries.
        > +" default: "%Y-%m-%d".
        > +" g:changelog_dateformat -
        > +" description: the format sent to strftime() to generate a date string.
        > +" default: "%Y-%m-%d".
        > +" g:changelog_username -
        > +" description: the username to use in ChangeLog entries
        > +" default: try to deduce it from environment variables and system files.
        > +" Local Mappings:
        > +" <Leader>o -
        > +" adds a new changelog entry for the current user for the current date.
        > +" Global Mappings:
        > +" <Leader>o -
        > +" switches to the ChangeLog buffer opened for the current directory, or
        > +" opens it in a new buffer if it exists in the current directory. Then
        > +" it does the same as the local <Leader>o described above.
        > +" Notes:
        > +" run 'runtime ftplugin/changelog.vim' to enable the global mapping for
        > +" changelog files.
        > +" TODO:
        > +" should we perhaps open the ChangeLog file even if it doesn't exist already?
        > +" Problem is that you might end up with ChangeLog files all over the place.
        > +
        > +" If 'filetype' isn't "changelog", we must have been to add ChangeLog opener
        > +if &filetype == 'changelog'
        > + if exists('b:did_ftplugin')
        > + finish
        > + endif
        > + let b:did_ftplugin = 1
        > +
        > + let s:cpo_save = &cpo
        > + set cpo&vim
        > +
        > + " Set up the format used for dates.
        > + if !exists('g:changelog_dateformat')
        > + if exists('g:changelog_timeformat')
        > + let g:changelog_dateformat = g:changelog_timeformat
        > + else
        > + let g:changelog_dateformat = "%Y-%m-%d"
        > + endif
        > + endif
        > +
        > + function! s:username()
        > + if exists('g:changelog_username')
        > + return g:changelog_username
        > + elseif $EMAIL != ""
        > + return $EMAIL
        > + elseif $EMAIL_ADDRESS != ""
        > + return $EMAIL_ADDRESS
        > + endif
        > +
        > + let login = s:login()
        > + return printf('%s <%s@%s>', s:name(login), login, s:hostname())
        > + endfunction
        > +
        > + function! s:login()
        > + return s:trimmed_system_with_default('whoami', 'unknown')
        > + endfunction
        > +
        > + function! s:trimmed_system_with_default(command, default)
        > + return s:first_line(s:system_with_default(a:command, a:default))
        > + endfunction
        > +
        > + function! s:system_with_default(command, default)
        > + let output = system(a:command)
        > + if v:shell_error
        > + return default
        > + endif
        > + return output
        > + endfunction
        > +
        > + function! s:first_line(string)
        > + return substitute(a:string, '\n.*$', "", "")
        > + endfunction
        > +
        > + function! s:name(login)
        > + for name in [s:gecos_name(a:login), $NAME, s:capitalize(a:login)]
        > + if name != ""
        > + return name
        > + endif
        > + endfor
        > + endfunction
        > +
        > + function! s:gecos_name(login)
        > + for line in s:try_reading_file('/etc/passwd')
        > + if line =~ '^' . a:login . ':'
        > + return substitute(s:passwd_field(line, 5), '&', s:capitalize(a:login), "")
        > + endif
        > + endfor
        > + return ""
        > + endfunction
        > +
        > + function! s:try_reading_file(path)
        > + try
        > + return readfile(a:path)
        > + endtry
        > + return []
        > + endfunction
        > +
        > + function! s:passwd_field(line, field)
        > + let fields = split(a:line, ':', 1)
        > + if len(fields) < field
        > + return ""
        > + endif
        > + return fields[field - 1]
        > + endfunction
        > +
        > + function! s:capitalize(word)
        > + return toupper(a:word[0]) . strpart(a:word, 1)
        > + endfunction
        > +
        > + function! s:hostname()
        > + return s:trimmed_system_with_default('hostname', 'localhost')
        > + endfunction
        > +
        > + " Format used for new date entries.
        > + if !exists('g:changelog_new_date_format')
        > + let g:changelog_new_date_format = "%d %u\n\n\t* %c\n\n"
        > + endif
        > +
        > + " Format used for new entries to current date entry.
        > + if !exists('g:changelog_new_entry_format')
        > + let g:changelog_new_entry_format = "\t* %c"
        > + endif
        > +
        > + " Regular expression used to find a given date entry.
        > + if !exists('g:changelog_date_entry_search')
        > + let g:changelog_date_entry_search = '^\s*%d\_s*%u'
        > + endif
        > +
        > + " Regular expression used to find the end of a date entry
        > + if !exists('g:changelog_date_end_entry_search')
        > + let g:changelog_date_end_entry_search = '^\s*$'
        > + endif
        > +
        > +
        > + " Substitutes specific items in new date-entry formats and search strings.
        > + " Can be done with substitute of course, but unclean, and need \@! then.
        > + function! s:substitute_items(str, date, user)
        > + let str = a:str
        > + let middles = {'%': '%', 'd': a:date, 'u': a:user, 'c': '{cursor}'}
        > + let i = stridx(str, '%')
        > + while i != -1
        > + let inc = 0
        > + if has_key(middles, str[i + 1])
        > + let mid = middles[str[i + 1]]
        > + let str = strpart(str, 0, i) . mid . strpart(str, i + 2)
        > + let inc = strlen(mid)
        > + endif
        > + let i = stridx(str, '%', i + 1 + inc)
        > + endwhile
        > + return str
        > + endfunction
        > +
        > + " Position the cursor once we've done all the funky substitution.
        > + function! s:position_cursor()
        > + if search('{cursor}') > 0
        > + let lnum = line('.')
        > + let line = getline(lnum)
        > + let cursor = stridx(line, '{cursor}')
        > + call setline(lnum, substitute(line, '{cursor}', '', ''))
        > + endif
        > + startinsert!
        > + endfunction
        > +
        > + " Internal function to create a new entry in the ChangeLog.
        > + function! s:new_changelog_entry(...)
        > + " Deal with 'paste' option.
        > + let save_paste = &paste
        > + let &paste = 1
        > + call cursor(1, 1)
        > + " Look for an entry for today by our user.
        > + let date = strftime(g:changelog_dateformat)
        > + let search = s:substitute_items(g:changelog_date_entry_search, date,
        > + \ g:changelog_username)
        > + if search(search) > 0
        > + " Ok, now we look for the end of the date entry, and add an entry.
        > + call cursor(nextnonblank(line('.') + 1), 1)
        > + if search(g:changelog_date_end_entry_search, 'W') > 0
        > + let p = (line('.') == line('$')) ? line('.') : line('.') - 1
        > + else
        > + let p = line('.')
        > + endif
        > + let ls = split(s:substitute_items(g:changelog_new_entry_format, '', ''),
        > + \ '\n')
        > + call append(p, ls)
        > + call cursor(p + 1, 1)
        > + else
        > + " Flag for removing empty lines at end of new ChangeLogs.
        > + let remove_empty = line('$') == 1
        > +
        > + " No entry today, so create a date-user header and insert an entry.
        > + let todays_entry = s:substitute_items(g:changelog_new_date_format,
        > + \ date, g:changelog_username)
        > + " Make sure we have a cursor positioning.
        > + if stridx(todays_entry, '{cursor}') == -1
        > + let todays_entry = todays_entry . '{cursor}'
        > + endif
        > +
        > + " Now do the work.
        > + call append(0, split(todays_entry, '\n'))
        > +
        > + " Remove empty lines at end of file.
        > + if remove_empty
        > + $-/^\s*$/-1,$delete
        > + endif
        > +
        > + " Reposition cursor once we're done.
        > + call cursor(1, 1)
        > + endif
        > +
        > + call s:position_cursor()
        > +
        > + " And reset 'paste' option
        > + let &paste = save_paste
        > + endfunction
        > +
        > + if exists(":NewChangelogEntry") != 2
        > + noremap <buffer> <silent> <Leader>o <Esc>:call <SID>new_changelog_entry()<CR>
        > + command! -nargs=0 NewChangelogEntry call s:new_changelog_entry()
        > + endif
        > +
        > + let b:undo_ftplugin = "setl com< fo< et< ai<"
        > +
        > + setlocal comments=
        > + setlocal formatoptions+=t
        > + setlocal noexpandtab
        > + setlocal autoindent
        > +
        > + if &textwidth == 0
        > + setlocal textwidth=78
        > + let b:undo_ftplugin .= " tw<"
        > + endif
        > +
        > + let &cpo = s:cpo_save
        > + unlet s:cpo_save
        > +else
        > + let s:cpo_save = &cpo
        > + set cpo&vim
        > +
        > + " Add the Changelog opening mapping
        > + nnoremap <silent> <Leader>o :call <SID>open_changelog()<CR>
        > +
        > + function! s:open_changelog()
        > + let path = expand('%:p:h')
        > + if exists('b:changelog_path')
        > + let changelog = b:changelog_path
        > + else
        > + if exists('b:changelog_name')
        > + let name = b:changelog_name
        > + else
        > + let name = 'ChangeLog'
        > + endif
        > + while isdirectory(path)
        > + let changelog = path . '/' . name
        > + if filereadable(changelog)
        > + break
        > + endif
        > + let parent = substitute(path, '/\+[^/]*$', "", "")
        > + if path == parent
        > + break
        > + endif
        > + let path = parent
        > + endwhile
        > + endif
        > + if !filereadable(changelog)
        > + return
        > + endif
        > +
        > + if exists('b:changelog_entry_prefix')
        > + let prefix = call(b:changelog_entry_prefix, [])
        > + else
        > + let prefix = substitute(strpart(expand('%:p'), strlen(path)), '^/\+', "", "") . ':'
        > + endif
        > + if !empty(prefix)
        > + let prefix = ' ' . prefix
        > + endif
        > +
        > + let buf = bufnr(changelog)
        > + if buf != -1
        > + if bufwinnr(buf) != -1
        > + execute bufwinnr(buf) . 'wincmd w'
        > + else
        > + execute 'sbuffer' buf
        > + endif
        > + else
        > + execute 'split' fnameescape(changelog)
        > + endif
        > +
        > + call s:new_changelog_entry(prefix)
        > + endfunction
        > +
        > + let &cpo = s:cpo_save
        > + unlet s:cpo_save
        > +endif


        Best regards,
        Tony.
        --
        Meekness is uncommon patience in planning a worthwhile revenge.

        --
        --
        You received this message from the "vim_use" maillist.
        Do not top-post! Type your reply below the text you are replying to.
        For more information, visit http://www.vim.org/maillist.php

        ---
        You received this message because you are subscribed to the Google Groups "vim_use" group.
        To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@....
        For more options, visit https://groups.google.com/groups/opt_out.
      • Josh Stone
        On Thu, Dec 12, 2013 at 8:14 PM, Tony Mechelynck ... OK, so I suppose if new_changelog_entry() isn t going to do anything with the prefix, and perhaps never
        Message 3 of 4 , Dec 14, 2013
          On Thu, Dec 12, 2013 at 8:14 PM, Tony Mechelynck
          <antoine.mechelynck@...> wrote:
          >
          > Indeed, AFAICT, before the change any number of arguments could be passed but they wouldn't be used. This seems weird but there might be reasons for it. For instance avoiding the error in s:open_changelog without fixing it. Doesn't look very convincing to me.

          OK, so I suppose if new_changelog_entry() isn't going to do anything
          with the prefix, and perhaps never has, then open_changelog should
          just omit the parameter as well? It would be nice to pre-fill the
          relative filename, but it should at least not throw errors like this.


          Josh

          --
          --
          You received this message from the "vim_use" maillist.
          Do not top-post! Type your reply below the text you are replying to.
          For more information, visit http://www.vim.org/maillist.php

          ---
          You received this message because you are subscribed to the Google Groups "vim_use" group.
          To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@....
          For more options, visit https://groups.google.com/groups/opt_out.
        • Jonathan Wakely
          ... I reported this to the maintainer but forgot to submit a fix upstream. I ve been using this patch for months: diff -r acf7368a2acc
          Message 4 of 4 , Jan 9, 2014
            On Sunday, December 15, 2013 1:41:38 AM UTC, Josh Stone wrote:
            >
            > OK, so I suppose if new_changelog_entry() isn't going to do anything
            > with the prefix, and perhaps never has, then open_changelog should
            > just omit the parameter as well? It would be nice to pre-fill the
            > relative filename, but it should at least not throw errors like this.

            I reported this to the maintainer but forgot to submit a fix upstream. I've been using this patch for months:

            diff -r acf7368a2acc runtime/ftplugin/changelog.vim
            --- a/runtime/ftplugin/changelog.vim Thu Mar 21 22:53:50 2013 +0100
            +++ b/runtime/ftplugin/changelog.vim Thu Jan 09 13:05:16 2014 +0000
            @@ -294,7 +294,7 @@
            execute 'split' fnameescape(changelog)
            endif

            - call s:new_changelog_entry(prefix)
            + call s:new_changelog_entry()
            endfunction

            let &cpo = s:cpo_save

            --
            --
            You received this message from the "vim_use" maillist.
            Do not top-post! Type your reply below the text you are replying to.
            For more information, visit http://www.vim.org/maillist.php

            ---
            You received this message because you are subscribed to the Google Groups "vim_use" group.
            To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@....
            For more options, visit https://groups.google.com/groups/opt_out.
          Your message has been successfully submitted and would be delivered to recipients shortly.