Thursday, March 22, 2018

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

Hi,

On Thu, Mar 22, 2018 at 12:36 AM, zechfox <zechfox@gmail.com> wrote:
> 在 2017年11月16日星期四 UTC+8下午10:44:41,Yegappan写道:
>> 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
>
> Is that possible use 'title' to get quickfix list?
>

The 'title' of a quickfix list is not unique. More than one quickfix
list can have the same title. So a 'title' string cannot be used
to uniquely identify a quickfix list.

>
> As the vim help documents said:
> id get information for the quickfix list with
> quickfix-ID; zero means the id for the
> current list or the list specified by "nr"
>
> the 'current list' maybe changed by other plugin
>

A plugin can create a quickfix list and store/cache the id of the
list immediately in a plugin variable.

Regards,
Yegappan

--
--
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: