diff --git a/denops/ddu/ddu.ts b/denops/ddu/ddu.ts index a7183f7..2662140 100644 --- a/denops/ddu/ddu.ts +++ b/denops/ddu/ddu.ts @@ -838,18 +838,41 @@ export class Ddu { } } - expandItems( + async expandItems( denops: Denops, items: ExpandItem[], - ): void { + ): Promise { // Clear queue this.expandedPaths.clear(); - for (const item of items) { + if (items.length === 1) { + // If items is only one item, search the item by `search` param after expanding. + const item = items[0]; const maxLevel = item.maxLevel && item.maxLevel < 0 ? -1 : item.item.__level + (item.maxLevel ?? 0); - this.expandItem(denops, item.item, maxLevel, item.search); + await this.expandItem(denops, item.item, maxLevel, item.search, false); + return; + } + + await Promise.all(items.map((item) => { + const maxLevel = item.maxLevel && item.maxLevel < 0 + ? -1 + : item.item.__level + (item.maxLevel ?? 0); + return this.expandItem(denops, item.item, maxLevel, item.search, true); + })); + + const [ui, uiOptions, uiParams] = await this.getUi(denops); + if (ui && !this.finished) { + await uiRedraw( + denops, + this.lock, + this.context, + this.options, + ui, + uiOptions, + uiParams, + ); } } @@ -858,7 +881,8 @@ export class Ddu { parent: DduItem, maxLevel: number, search?: string, - ): Promise { + preventRedraw?: boolean, + ): Promise { if (parent.__level < 0) { return; } @@ -878,8 +902,6 @@ export class Ddu { sourceOptions.path = parent.treePath ?? parent.word; this.context.path = sourceOptions.path; - this.finished = false; - let children: DduItem[] = []; for await ( @@ -902,6 +924,9 @@ export class Ddu { ); children = children.concat(newItems); } + if (this.finished) { + return; + } const filters = sourceOptions.matchers.concat( sourceOptions.sorters, @@ -914,82 +939,83 @@ export class Ddu { this.input, children, ); - await this.redrawExpandItem( - denops, - parent, - children, - maxLevel, - search, - ); - } - async redrawExpandItem( - denops: Denops, - parent: DduItem, - children: DduItem[], - maxLevel: number, - search?: string, - ): Promise { const [ui, uiOptions, uiParams] = await this.getUi(denops); - if (!ui) { - return; + if (ui && !this.finished) { + await ui.expandItem({ + denops, + context: this.context, + options: this.options, + uiOptions, + uiParams, + parent, + children, + }); } - await ui.expandItem({ - denops, - context: this.context, - options: this.options, - uiOptions, - uiParams, - parent, - children, - }); + let searchedItem: DduItem | undefined; if (maxLevel < 0 || parent.__level < maxLevel) { - for (const child of children) { - // Note: Skip hidden directory - if ( - child.isTree && child.treePath && + await Promise.all( + children.filter(( + child, + ) => (child.isTree && child.treePath && (!search || isParentPath(child.treePath, search)) && - !basename(child.treePath).startsWith(".") - ) { + // Note: Skip hidden directory + !basename(child.treePath).startsWith(".")) + ).map(async (child: DduItem) => { // Expand is not completed yet. - this.expandItem(denops, child, maxLevel, search); - } - } + const hit = await this.expandItem( + denops, + child, + maxLevel, + search, + true, + ); + if (hit) { + searchedItem = hit; + } + }), + ); } - this.expandedPaths.delete(parent.treePath); - - // To redraw items, expandItems must be empty - if (this.expandedPaths.size != 0) { - return; + if ( + !searchedItem && parent.treePath && + (!search || isParentPath(parent.treePath, search)) + ) { + searchedItem = search + ? children.find((item) => search == item.treePath ?? item.word) + : parent; } - await uiRedraw( - denops, - this.lock, - this.context, - this.options, - ui, - uiOptions, - uiParams, - ); - - const searchItem = search - ? children.find((item) => search == item.treePath ?? item.word) - : parent; - - if (searchItem) { - await ui.searchItem({ + if (ui && !this.finished && !preventRedraw) { + await uiRedraw( denops, - context: this.context, - options: this.options, + this.lock, + this.context, + this.options, + ui, uiOptions, uiParams, - item: searchItem, - }); + ); + + const searchItem = search + ? children.find((item) => search == item.treePath ?? item.word) + : parent; + + if (searchItem) { + await ui.searchItem({ + denops, + context: this.context, + options: this.options, + uiOptions, + uiParams, + item: searchItem, + }); + } } + + return searchedItem; } async collapseItems(