Friday, November 17, 2017

Re: Updating a quickfix/location list asynchronously without interfering with another plugin

On 06:44 Thu 16 Nov , Yegappan Lakshmanan wrote:
> Hi all,
>
> There was a recent thread in reddit/r/vim about two Vim plugins updating
> the same quickfix list at the same time thereby interfering with each other:
>
> https://www.reddit.com/r/vim/comments/7c5f1a/two_plugins_writing_to_quickfixloc_list_at_the/
>
> As many other plugin authors may need to know how to use the new Vim quickfix
> features to avoid this, I am sending this e-mail.
>
> Vim has many plugins (vim-go, ale, etc.) that use the quickfix/location list
> feature. Some of these plugins process the output of an external command and
> update the quickfix list asynchronously as the output becomes available.
>
> Updating the quickfix list asynchronously opens up a possibility that two or
> more plugins may try to update the same quickfix list with different output.
> Also when a plugin is updating the quickfix list in the background, the user
> may issue a command that creates or updates a quickfix list. The plugin may
> then incorrectly use this new list to add the entries.
>
> The various commands that create or modify a quickfix list (cfile, cgetfile,
> caddfile, cbuffer, cgetbuffer, caddbuffer, cexpr, cgetexpr, caddexpr, make,
> grep, grepadd, vimgrep and vimgrepadd) operate only on the current quickfix
> list. A plugin using these commands to update the quickfix list can interfere
> with another plugin.
>
> To avoid these issues, the Vim functions getqflist() and setqflist() can be
> used to operate on any list in the quickfix stack. A list in the stack can be
> specified using the quickfix identifier. So if a Vim plugin uses these
> functions to operate on a specific quickfix list then it can avoid interfering
> with the operation of another plugin operating on another quickfix list.
>
> The identifier of a quickfix list can be obtained using:
>
> let qfid = getqflist({'id' : 0}).id
>
> When adding new entries, the plugin can use setqflist() with this identifier:
>
> call setqflist([], 'a', {'id' : qfid, 'items' : newitems})
>
> To parse the output of a command and add the quickfix entries, the plugin can
> use the following:
>
> call setqflist([], 'a', {'id' : qfid, 'lines' : cmdoutput})
>
> Note that in the previous command, the current 'errorformat' option setting is
> used to parse the command output. This setting might have been changed either
> by the user or by some other plugin to some other value. To parse the command
> output using a specific 'errorformat' setting, the plugin can use:
>
> call setqflist([], 'a', {'id' : qfid, 'lines' : cmdoutput, 'efm' : myefm})
>
> If a more than 10 quickfix lists are added to the quickfix stack, then the
> oldest quickfix list is removed. The plugin should check whether the quickfix
> list it is using is still valid using the following:
>
> if has_key(getqflist({'id' : qfid}), 'id')
> " List is still valid
> endif
>
> In summary, a plugin can use the following steps to asynchronously process a
> command output and update a quickfix list:
>
> 1. Create an empty quickfix list:
>
> call setqflist([], ' ', {'title' : 'Output from command abc'})
>
> 2. Save the newly created quickfix list identifier:
>
> let qfid = getqflist({'id' : 0}).id
>
> 3. Start a command in the background using job_start()
>
> 4. In the job callback function, check if the quickfix list is still present:
>
> if has_key(getqflist({'id' : qfid}), 'id')
> " Still present
> " Update the list
> else
> " List is removed. Stop the background job.
> job_stop(....)
> endif
>
> 5. Process the command output and update the quickfix list using one
> of the following
> calls:
>
> call setqflist([], 'a', {'id' : qfid, 'lines' : cmdoutput, 'efm' : myefm})
>
> or
>
> call setqflist([], 'a', {'id' : qfid, 'items' : newitems})
>
>
> - Yegappan

Thanks for the detailed explanation!

Best regards,
Marcin

--
--
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@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: