summaryrefslogtreecommitdiff
path: root/dot-oh-my-zsh/custom/plugins/zsh-autocomplete/scripts/.autocomplete.async
blob: 2965498c0dbd9b3fe6116936c1afea7fcd4ab26b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
#!/bin/zsh
zmodload -F zsh/zpty b:zpty
zmodload -F zsh/parameter p:funcstack p:functions p:parameters
zmodload -F zsh/system b:sysopen p:sysparams
zmodload -F zsh/zselect b:zselect
zmodload -F zsh/terminfo b:echoti p:terminfo
zmodload -F zsh/zutil b:zparseopts
builtin autoload -RUz add-zle-hook-widget

typeset -gHi _autocomplete__buffer_start_line=1
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=yes
local -Pa log_functions=()

builtin zle -N history-incremental-search-backward .autocomplete.async.history-incremental-search
builtin zle -N history-incremental-search-forward .autocomplete.async.history-incremental-search

.autocomplete.async.precmd() {
  local -PF delay=
  builtin zstyle -s :autocomplete: min-delay delay
  (( delay += 0.1 ))
  typeset -gHF _autocomplete__async_avg_duration=$delay

  # Start names with `.` to avoid getting wrapped by syntax highlighting.
  builtin zle -N .autocomplete.async.pty.zle-widget
  builtin zle -C .autocomplete.async.pty.completion-widget list-choices \
      .autocomplete.async.pty.completion-widget
  builtin zle -N .autocomplete.async.complete.fd-widget
  builtin zle -C ._list_choices list-choices .autocomplete.async.list-choices.completion-widget

  if [[ -v functions[_zsh_highlight_call_widget] ]]; then
    _zsh_highlight_call_widget() {
      .autocomplete.zle-flags $WIDGET
      builtin zle "$@"
    }
  fi

  if [[ -v functions[_zsh_autosuggest_highlight_apply] ]]; then
    local -P action=
    for action in clear modify fetch accept partial_accept execute enable disable toggle; do
      # Set flags according to widget name.
      eval "_zsh_autosuggest_widget_$action() {
        .autocomplete.zle-flags \$WIDGET
        _zsh_autosuggest_$action \"\$@\"
      }"
    done
    _zsh_autosuggest_widget_suggest() {
      .autocomplete.zle-flags  # Maintain previously set flags.
      _zsh_autosuggest_suggest "$@"
    }
  fi

  .autocomplete.patch _message

  add-zle-hook-widget line-init .autocomplete.async.read-cursor-position
  add-zle-hook-widget line-init .autocomplete.async.reset-context
  add-zle-hook-widget line-init .autocomplete.async.complete

  add-zle-hook-widget line-pre-redraw .autocomplete.async.complete
  add-zle-hook-widget line-finish .autocomplete.async.clear
  add-zle-hook-widget isearch-update .autocomplete.async.isearch-update
  add-zle-hook-widget isearch-exit .autocomplete.async.isearch-exit

  add-zsh-hook zshexit .autocomplete.async.stop
}

.autocomplete.async.read-cursor-position() {
  emulate -L zsh
  # Cannot set strict shell options here, because other programs' async
  # callbacks can interrupt the code and then get executed in the same context.
  # See https://github.com/marlonrichert/zsh-autocomplete/issues/342

  (( KEYS_QUEUED_COUNT || PENDING )) &&
      return

  # $MC_SID is set when we're in a subshell started by Midnight Commander.
  # See https://github.com/marlonrichert/zsh-autocomplete/issues/269
  if [[ -v MC_SID || ! ( -v terminfo[u6] && -v terminfo[u7] ) ]]; then
    local -i max_lines=
    builtin zstyle -s ":autocomplete:${curcontext}:" list-lines max_lines ||
        max_lines=16
    typeset -gHi _autocomplete__buffer_start_line=$(( min( max( LINES - max_lines, 1 ), LINES ) ))
    return 0
  fi

  # Cursor position report (u6) always contains two %d markers.
  local -Pa CPR=( "${(s:%d:)$( echoti u6 )}" )

  # If there is a %i before the first %d, then decrement both %d values by 1.
  local -Pi i=${${${(M)CPR[1]%'%i'}:+1}:-0}
  CPR[1]=${CPR[1]%'%i'}

  local REPLY=
  local -P Y=
  echoti u7  # Send cursor position request.

  # Parse the cursor position report.
  read -rsk $#CPR[1]  # Discard the preamble.
  while [[ $REPLY != $CPR[2] ]]; do
    read -rsk
    Y+=$REPLY
  done
  Y="${Y%$CPR[2]}"  # Discard the separator.
  Y=${(M)Y%%<->}    # Keep trailing digits only (to work around input pollution).

  # Flush the rest.
  while [[ $REPLY != $CPR[3] ]]; do
    read -rsk
  done

  typeset -gHi _autocomplete__buffer_start_line=$(( min( max( Y - i, 1 ), LINES ) ))
}

.autocomplete.async.history-incremental-search() {
  if [[ $curcontext == $WIDGET* ]]; then
    unset curcontext
  else
    typeset -gH curcontext=${WIDGET}:::
  fi
  [[ -o sharehistory ]] &&
      fc -RI  # Get new history events from file.
  .autocomplete.async.start
}

.autocomplete.async.reset-context() {
  local context
  builtin zstyle -s :autocomplete: default-context context
  typeset -gH curcontext=$context
  return 0
}

.autocomplete.async.isearch-update() {
  typeset -gHi _autocomplete__isearch=1
}

.autocomplete.async.isearch-exit() {
  .autocomplete.zle-flags $LASTWIDGET
  unset _autocomplete__isearch
}

.autocomplete.async.complete() {
  .autocomplete.zle-flags $LASTWIDGET

  (( KEYS_QUEUED_COUNT || PENDING )) &&
      return

  [[ -v functions[_zsh_highlight] ]] &&
      _zsh_highlight
  typeset -gH _autocomplete__highlight=( $region_highlight[@] )
  [[ -v functions[_zsh_autosuggest_highlight_apply] ]] &&
      _zsh_autosuggest_highlight_apply

  [[ $LASTWIDGET == .autocomplete.async.complete.fd-widget ]] &&
      return

  .autocomplete.async.stop

  if (( REGION_ACTIVE )) ||
      [[ -v _autocomplete__isearch && $LASTWIDGET == *(incremental|isearch)* ]]; then
    builtin zle -Rc
    return 0
  fi

  [[ $LASTWIDGET ==
        (_complete_help|list-expand|(|.)(describe-key-briefly|what-cursor-position|where-is)) ]] &&
      return

  [[ $_lastcomp[insert] == *unambiguous ]] &&
      builtin zle .auto-suffix-retain  # Make the cursor stay in the right place.

  .autocomplete.async.start
  return 0
}

.autocomplete.async.clear() {
  builtin zle -Rc
  unset _autocomplete__isearch
  .autocomplete.async.stop
  .autocomplete.async.reset-context
  return 0
}

.autocomplete.async.stop() {
  local fd=$_autocomplete__async_complete_fd
  unset _autocomplete__async_complete_fd
  unset _autocomplete__mesg _autocomplete__comp_mesg _autocomplete__words _autocomplete__current
  if [[ $fd == <-> ]]; then
    builtin zle -F $fd 2> /dev/null
    exec {fd}<&-
  fi
}

.autocomplete.async.start() {
  local fd=
  sysopen -r -o cloexec -u fd <(
    typeset -F SECONDS=0
    setopt promptsubst
    PS4=$_autocomplete__ps4
    .autocomplete.async.start.inner
  )
  builtin zle -Fw "$fd" .autocomplete.async.complete.fd-widget
  typeset -gH _autocomplete__async_complete_fd=$fd

  # There's a weird bug in Zsh < 5.8, where ^C stops working unless we force a fork.
  # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
  command true
}

.autocomplete.async.start.inner() {
  {
    local -F min_delay=
    builtin zstyle -s :autocomplete: min-delay min_delay ||
        min_delay=0.05
    
    # Directly using $(( [#10] 100 * max( 0, min_delay - SECONDS ) )) leads to 0
    # in Zsh >= 5.9, as the result of the max call is converted to an integer.
    # See https://github.com/marlonrichert/zsh-autocomplete/issues/441
    local -i timeout=$(( 100 * max( 0, min_delay - SECONDS ) ))
    zselect -t $timeout

    local -P hooks=( chpwd periodic precmd preexec zshaddhistory zshexit )
    builtin unset ${^hooks}_functions &> /dev/null
    $hooks[@] () { : }

    local -P hook=
    for hook in \
        zle-{isearch-{exit,update},line-{pre-redraw,init,finish},history-line-set,keymap-select}
    do
      builtin zle -N $hook .autocomplete.async.pty.no-op
    done
    {
      local REPLY=
      zpty AUTOCOMPLETE .autocomplete.async.pty
      local -Pi fd=$REPLY

      zpty -w AUTOCOMPLETE $'\t'

      local header=
      zpty -r AUTOCOMPLETE header $'*\C-B'

      local -a reply=()
      local text=

      # Directly using $(( [#10] 100 * max( 0, 100 * _autocomplete__async_avg_duration - SECONDS ) ) ))
      # leads to 0 in Zsh >= 5.9, as the result of the max call is converted to an integer.
      # See https://github.com/marlonrichert/zsh-autocomplete/issues/441
      local -i timeout=$(( 100 * max( 0, 100 * _autocomplete__async_avg_duration - SECONDS ) ))
      zselect -rt $timeout "$fd" &&
          zpty -r AUTOCOMPLETE text $'*\C-C'
    } always {
      zpty -d AUTOCOMPLETE
    }
  } always {
    # Always produce output, so we always reach the callback, so we can close the fd and unset
    # $_autocomplete__async_complete_fd (if necessary).
    print -rNC1 -- "$SECONDS" "${text%$'\0\C-C'}"
  }
} 2>>| $_autocomplete__log_async
log_functions+=( .autocomplete.async.start.inner )

.autocomplete.async.pty() {
  typeset -gH _autocomplete__lbuffer="$LBUFFER" _autocomplete__rbuffer="$RBUFFER"

  builtin bindkey $'\t' .autocomplete.async.pty.zle-widget
  local __tmp__=
  builtin vared __tmp__
} 2>>| $_autocomplete__log_pty
log_functions+=( .autocomplete.async.pty )

.autocomplete.async.pty.no-op() {
  :
}

.autocomplete.async.pty.zle-widget() {
  .autocomplete.async.pty.zle-widget.inner "$@"
}

.autocomplete.async.pty.zle-widget.inner() {
  # The completion widget sometimes returns without calling its function. So, we need to print all
  # our control characters here, to ensure we don't end up waiting endlessly to read them.
  {
    print -n -- '\C-B'
    LBUFFER=$_autocomplete__lbuffer
    RBUFFER=$_autocomplete__rbuffer

    setopt $_autocomplete__comp_opts[@]
    [[ -n $curcontext ]] &&
        setopt $_autocomplete__ctxt_opts[@]
    builtin zle .autocomplete.async.pty.completion-widget -w 2> /dev/null
  } always {
    print -rNC1 -- \
        "$_autocomplete__list_lines" "$_autocomplete__mesg" "$_autocomplete__comp_mesg[@]" $'\C-C'
    builtin kill $sysparams[pid]
  }
} 2>>| $_autocomplete__log_pty
log_functions+=( .autocomplete.async.pty.zle-widget.inner )

.autocomplete.async.pty.completion-widget() {
  .autocomplete.async.pty.completion-widget.inner "$@"
}

.autocomplete.async.pty.completion-widget.inner() {
  if ! .autocomplete.async.sufficient-input; then
    typeset -gHi _autocomplete__list_lines=0
    return
  fi
  if .autocomplete.async.same-state; then
    typeset -gHi _autocomplete__list_lines=$_lastcomp[list_lines]
    return
  fi

  unset _autocomplete__mesg _autocomplete__comp_mesg
  {
    local curcontext=${curcontext:-list-choices:::}
    unset 'compstate[vared]'

    _message() {
      compadd() {
        typeset -gHa _autocomplete__comp_mesg=( "$@" )
        builtin compadd "$@"
      }
      zformat() {
        builtin zformat "$@"
        typeset -gHa _autocomplete__comp_mesg=( "$gopt[@]" -x "$format" )
      }
      .autocomplete._message "$@"
      unfunction zformat
      functions[compadd]="$functions[.autocomplete.compadd]"
    }

    local +h -a comppostfuncs=( .autocomplete.async.pty.message )
    _main_complete
  } always {
    typeset -gHi _autocomplete__list_lines=$compstate[list_lines]
  }
} 2>>| $_autocomplete__log_pty
log_functions+=( .autocomplete.async.pty.completion-widget.inner )

.autocomplete.async.pty.message() {
  typeset -gH _autocomplete__mesg=$mesg
  return 0
}

.autocomplete.async.complete.fd-widget() {
  setopt promptsubst
  local +h PS4=$_autocomplete__ps4
  .autocomplete.async.complete.fd-widget.inner "$@"
}

.autocomplete.async.complete.fd-widget.inner() {
  local -i fd=$1
  {
    builtin zle -F $fd # Unhook ourselves immediately, so we don't get called more than once.

    # Ensure our input will not be stopped.
    unset _autocomplete__async_complete_fd

    .autocomplete.zle-flags ||
        return 0

    local -a reply=()
    IFS=$'\0' read -rAu $fd
    shift -p reply
  } always {
    exec {fd}<&-
  }

  unset _autocomplete__mesg _autocomplete__comp_mesg

  # If a widget can't be called, zle always returns true.
  # Thus, we return false on purpose, so we can check if our widget got called.
  setopt $_autocomplete__comp_opts[@]
  [[ -n $curcontext ]] &&
      setopt $_autocomplete__ctxt_opts[@]
  if ! builtin zle ._list_choices -w "$reply[@]" 2>>| $_autocomplete__log; then
    region_highlight=( "$_autocomplete__highlight[@]" )
    [[ -v functions[_zsh_autosuggest_highlight_apply] ]] &&
        _zsh_autosuggest_highlight_apply

    # Refresh if and only if our widget got called. Otherwise, Zsh will crash (eventually).
    builtin zle -R
  else
    .autocomplete.async.stop
  fi
  return 0
} 2>>| $_autocomplete__log
log_functions+=( .autocomplete.async.complete.fd-widget.inner )

.autocomplete.async.sufficient-input() {
  # Don't check the input if we're not doing normal autocompletion.
  [[ -n $curcontext ]] &&
      return

  local min_input=
  builtin zstyle -s :autocomplete:list-choices min-input min_input ||
      min_input=0
  local ignored=
  builtin zstyle -s :autocomplete:list-choices ignored-input ignored
  if (( ${#words[@]} == 1 && ${#words[CURRENT]} < min_input )) ||
      [[ -n $words[CURRENT] && $words[CURRENT] == $~ignored ]]; then
    compstate[list]=
    false
  else
    true
  fi
}
# functions -T .autocomplete.async.sufficient-input

.autocomplete.async.same-state() {
  [[ $_autocomplete__words == $words && $_autocomplete__current == $CURRENT ]]
}

.autocomplete.async.list-choices.completion-widget() {
  unset _autocomplete__mesg _autocomplete__comp_mesg _autocomplete__words _autocomplete__current

  if [[ $1 != <->.<-> || $2 != <-> ]]; then
    compstate[list]=
    return
  fi

  .autocomplete.async.sufficient-input ||
      return 2

  local -PF _seconds_=$1
  local -Pi _list_lines_=$2
  local -P _mesg_=$3
  shift 3

  local +h -a comppostfuncs=( .autocomplete.async.list-choices.post "$comppostfuncs[@]" )
  if [[ -n $compstate[old_list] ]] && .autocomplete.async.same-state; then
    compstate[old_list]=keep
  elif [[ $_list_lines_ == 1 && -n $1 ]]; then
    builtin compadd "$@"
  elif [[ $_list_lines_ == 1 && -n $_mesg_ ]]; then
    builtin compadd -x "$_mesg_"
  else
    typeset -gHF _autocomplete__async_avg_duration=$((
        .1 * _seconds_ + .9 * _autocomplete__async_avg_duration
    ))
    if [[ -n $curcontext ]]; then
      _main_complete
    else
      local curcontext=list-choices:::
      .autocomplete.async.list-choices.main-complete
    fi
  fi

  typeset -gH _autocomplete__mesg=$_mesg_
  typeset -gHa _autocomplete__comp_mesg=( "$@" )
  typeset -gHa _autocomplete__words=( "$words[@]" )
  typeset -gHi _autocomplete__current=$CURRENT

  return 2  # Don't return 1, to prevent beeping.
} 2>>| $_autocomplete__log
log_functions+=( .autocomplete.async.list-choices.completion-widget )

.autocomplete.async.list-choices.post() {
  [[ -v _autocomplete__partial_list ]] &&
      builtin compadd -J -last- -x '%F{0}%K{14}(MORE)%f%k'
  compstate[insert]=
  unset MENUSELECT MENUMODE
}

.autocomplete.async.list-choices.main-complete() {
  {
    local -i min_lines=
    builtin zstyle -s ":autocomplete:${curcontext}:" list-lines min_lines ||
        min_lines=16
    min_lines=$(( min( LINES - ( 1 + BUFFERLINES ), min_lines ) ))
    local -Pi lines_below_buffer=$(( LINES - ( _autocomplete__buffer_start_line + BUFFERLINES ) ))
    local -i _autocomplete__max_lines=$(( max( min_lines, lines_below_buffer ) ))
    local -i _autocomplete__reserved_lines=0
    () {
      emulate -L zsh
      setopt $_autocomplete__func_opts[@]
      functions[compadd]=$functions[.autocomplete.async.compadd]
      # functions -T compadd .autocomplete.compadd #_describe
    } "$@"
    _main_complete "$@"
  } always {
    unfunction compadd comptags 2> /dev/null
  }
}

.autocomplete.async.compadd() {
  local -A _opts_=()
  local -a _Dopt_=() _dopt_=()
  zparseopts -A _opts_ -E -- D:=_Dopt_ E: J: O: V: x: X: d:

  if [[ ( -v _opts_[-x] && $# == 2 ) ]]; then
    .autocomplete.compadd "$@"
    return
  elif [[ $funcstack[(I)_describe] -gt 0 && -z $_Dopt_ ]]; then
    _autocomplete__reserved_lines=0
  fi

  local -P _displ_array_= _matches_array_=
  local -Pi _ret_=1 _new_nmatches_=-1 _new_list_lines_=-1
  local -Pi _avail_list_lines_=$((
      max( _autocomplete__max_lines - 1 - ${${_opts_[(i)-[Xx]]}:+1} - compstate[list_lines], 0 )
  ))

  if [[ -n $_Dopt_ ]]; then
    .autocomplete.compadd "$@"
    _ret_=$?

     (( funcstack[(I)_describe] )) ||
        return _ret_

    _displ_array_=$_opts_[-D]

    (( ${${(PA)_displ_array_}[(I)*:*]} )) ||
        return _ret_

    _matches_array_=$_opts_[-O]

    (( _avail_list_lines_ -= _autocomplete__reserved_lines ))
    _new_nmatches_=${(PA)#_displ_array_}
    _new_list_lines_=${#${(@u)${(PA)_displ_array_}[@]#*:}}
    (( _autocomplete__reserved_lines += _new_list_lines_ ))
  else
    _autocomplete__reserved_lines=0

    # (Note: Can't put comments inside expansions, without setting INTERACTIVE_COMMENTS.)
    local -Pa _out_=()
    _out_=( "${(0)"$(
        .autocomplete.compadd "$@"
        print -rNC1 -- "$compstate[list_lines]" "$compstate[nmatches]"
    )"}" )
    _new_list_lines_=$(( max( 0, $_out_[1] - $compstate[list_lines] ) ))
    _new_nmatches_=$((   max( 0, $_out_[2] - $compstate[nmatches]   ) ))
  fi

  if (( _new_list_lines_ <= _avail_list_lines_ )); then
    if [[ -z $_Dopt_ ]]; then
      .autocomplete.compadd "$@"
      _ret_=$?
    fi
    return _ret_
  fi

  if [[ -z $_Dopt_ ]]; then
    local -a _matches_=()
    .autocomplete.compadd -O _matches_ "$@" # Collect all matching completions.
    _matches_array_=_matches_
    _new_nmatches_=$#_matches_[@]
  fi

  local -a _groupname_=()

  # NOTE: This will overwrite the contents of $_opts_ !
  zparseopts -A _opts_ -D -E - k U d:=_dopt_ l=_dopt_ J:=_groupname_ V:=_groupname_

  set -- "$_groupname_[@]" "$@"
  [[ -z $_Dopt_ ]] &&
      _displ_array_=$_dopt_[-1]

  local -Pi _nmatches_per_line_=$(( 1.0 * _new_nmatches_ / _new_list_lines_ ))
  if [[ _nmatches_per_line_ -lt 1 && -z $_Dopt_ ]]; then
    # If we need more than one line per match, then make each match fit on one line.
    if [[ -z $_displ_array_ ]]; then
      local -a displ=( ${(PA)_matches_array_} )
      _dopt_=( -d displ )
      _displ_array_=displ
    fi
    _dopt_=( -l "$_dopt_[@]" )

    # WORKAROUND: Display strings that are exactly $COLUMNS wide are mistakenly
    # counted as spanning two lines, causing the dreaded
    # `zsh: do you wish to see all XX possibilities (YY lines)?`
    set -A $_displ_array_ ${(@r:COLUMNS-1:)${(PA)_displ_array_}[@]//$'\n'/\n}

    _nmatches_per_line_=1
  fi

  # Need to round this down _before_ subtracting or it will be effectively rounded up.
  local -Pi _fit_=$(( max( _avail_list_lines_, 0 ) * _nmatches_per_line_ ))
  local -Pi _trim_=$(( max( 0, _new_nmatches_ - _fit_ ) ))

  if (( _trim_ )); then
    [[ -n $_matches_array_ ]] &&
        shift -p $(( min( _trim_, ${(PA)#_matches_array_} ) )) $_matches_array_
    [[ -n $_displ_array_ ]] &&
        shift -p $(( min( _trim_, ${(PA)#_displ_array_} ) )) $_displ_array_
    typeset -gH _autocomplete__partial_list=$curtag

    # If we have to trim off matches, that means we've run out of screen space.
    # So, disable all further completion.
    comptags() {
      return 1
    }
  fi

  if [[ -z $_Dopt_ ]]; then
    _autocomplete.compadd_opts_len "$@"
    .autocomplete.compadd $_dopt_ "$@[1,?]" -a -- $_matches_array_
    _ret_=$?
  fi

  return _ret_
} 2>>| $_autocomplete__log
log_functions+=( .autocomplete.async.compadd )

typeset -gHa _autocomplete__log_functions=( $log_functions[@] )