core/pwsh/Win/menu.ps1
Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod handle_list { if ($this.is_show_tip) { $max_width = 0 $tip_max_height = 0 $this.filter_list = $this.filter_list | ForEach-Object { $symbol = ($_.symbol | ForEach-Object { $PSCompletions.config."symbol_$($_)" }) -join '' $pad = if ($symbol) { "$($PSCompletions.config.menu_between_item_and_symbol)$($symbol)" }else { '' } $name_with_symbol = "$($_.name[-1])$($pad)" $width = $this.get_length($name_with_symbol) if ($width -gt $max_width) { $max_width = $width } $json = $PSCompletions.data.$($PSCompletions.current_cmd) $info = $json.info if ($_.tip) { $tip = $PSCompletions.replace_content($_.tip) $tip_arr = $tip -split "`n" } else { $tip = ' ' $tip_arr = @() } if ($tip_arr.Count -gt $tip_max_height) { $tip_max_height = $tip_arr.Count } @{ name = $name_with_symbol value = $_.name[-1] width = $width tip = $tip } } if ($max_width -lt $PSCompletions.config.menu_list_min_width) { $max_width = $PSCompletions.config.menu_list_min_width } $this.list_max_width = $max_width $this.tip_max_height = $tip_max_height $this.filter_list | ForEach-Object { $pad = $max_width - $_.width $_.name = "$($_.name)$(' ' * $pad)" } if ($this.filter_list -is [array]) { $PSCompletions.is_single = $false } else { $PSCompletions.is_single = $true $this.filter_list = @($this.filter_list) } $this.ui_size.Width = 1 + $PSCompletions.config.menu_list_margin_left + $max_width + $PSCompletions.config.menu_list_margin_right + 1 } else { $max_width = 0 $this.filter_list = $this.filter_list | ForEach-Object { $symbol = ($PSCompletions.replace_content($_.symbol, ' ') -split ' ' | ForEach-Object { $PSCompletions.config."symbol_$($_)" }) -join '' $pad = if ($symbol) { "$($PSCompletions.config.menu_between_item_and_symbol)$($symbol)" }else { '' } $name_with_symbol = "$($_.name[-1])$($pad)" $width = $this.get_length($name_with_symbol) if ($width -gt $max_width) { $max_width = $width } @{ name = $name_with_symbol value = $_.name[-1] width = $width } } if ($max_width -lt $PSCompletions.config.menu_list_min_width) { $max_width = $PSCompletions.config.menu_list_min_width } $this.list_max_width = $max_width $this.filter_list | ForEach-Object { $pad = $max_width - $_.width $_.name = "$($_.name)$(' ' * $pad)" } if ($this.filter_list -is [array]) { $PSCompletions.is_single = $false } else { $PSCompletions.is_single = $true $this.filter_list = @($this.filter_list) } $this.ui_size.Width = 1 + $PSCompletions.config.menu_list_margin_left + $max_width + $PSCompletions.config.menu_list_margin_right + 1 } } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod parse_list { # X if ($PSCompletions.config.menu_list_follow_cursor) { $this.pos.X = $Host.UI.RawUI.CursorPosition.X # 如果跟随鼠标,如果在超过右侧边界,则向左偏移 if ($this.pos.X + $this.ui_size.Width -gt $Host.UI.RawUI.BufferSize.Width - 1) { $this.pos.X = $Host.UI.RawUI.BufferSize.Width - 1 - $this.ui_size.Width } } else { $this.pos.X = 0 } $this.pos_tip.X = if ($PSCompletions.config.menu_tip_follow_cursor) { $this.pos.X }else { 0 } # 当为 0 时,有几率出现渲染错误,所以坐标右移一点 if ($this.pos.x -eq 0) { $this.pos.x ++ } # Y $this.cursor_to_bottom = $Host.UI.RawUI.BufferSize.Height - $Host.UI.RawUI.CursorPosition.Y - 1 $this.cursor_to_top = $Host.UI.RawUI.CursorPosition.Y - $PSCompletions.config.menu_above_margin_bottom - 1 $this.is_show_above = if ($this.cursor_to_bottom -ge $this.cursor_to_top) { $false }else { $true } $this.ui_size.height = $this.filter_list.Count + 2 if ($this.is_show_above) { if ($PScompletions.config.menu_above_list_max_count -ne -1) { if ($this.filter_list.Count -gt $PScompletions.config.menu_above_list_max_count) { $this.ui_size.height = $PScompletions.config.menu_above_list_max_count + 2 } } if ($this.ui_size.height -gt $this.cursor_to_top) { $this.ui_size.height = $this.cursor_to_top } } else { if ($PScompletions.config.menu_below_list_max_count -ne -1) { if ($this.filter_list.Count -gt $PScompletions.config.menu_below_list_max_count) { $this.ui_size.height = $PScompletions.config.menu_below_list_max_count + 2 } } if ($this.ui_size.height -gt $this.cursor_to_bottom) { $this.ui_size.height = $this.cursor_to_bottom } } if ($this.is_show_above) { $usable_height = $this.cursor_to_top - $this.ui_size.height if ($this.tip_max_height -ge $usable_height) { $new_ui_height = $this.ui_size.height - ($this.tip_max_height - $usable_height) - 1 if ($new_ui_height -lt 3) { $this.is_show_tip = $false } else { $this.ui_size.height = $new_ui_height } } $this.pos.Y = $Host.UI.RawUI.CursorPosition.Y - $this.ui_size.height - $PSCompletions.config.menu_above_margin_bottom # 设置 tip 的 起始位置 $this.pos_tip.Y = $this.pos.Y - $this.tip_max_height - 1 if ($this.pos_tip.Y -lt 0) { $this.is_show_tip = $false } } else { $usable_height = $this.cursor_to_bottom - $this.ui_size.Height if ($this.tip_max_height -ge $usable_height) { $new_ui_height = $this.ui_size.height - ($this.tip_max_height - $usable_height) - 2 if ($new_ui_height -lt 3) { $this.is_show_tip = $false } else { $need_height = $this.pos.Y + $new_ui_height + 1 + $this.tip_max_height if ($need_height -ge $Host.UI.RawUI.BufferSize.Height) { $this.is_show_tip = $false } else { $this.ui_size.height = $new_ui_height $this.pos_tip.Y = $this.pos.Y + $new_ui_height + 1 } } } $this.pos.Y = $Host.UI.RawUI.CursorPosition.Y + 1 $this.pos_tip.Y = $this.pos.Y + $this.ui_size.height + 1 if ($this.pos_tip.Y -ge $Host.UI.RawUI.BufferSize.Height) { $this.is_show_tip = $false } } $this.page_max_index = $this.ui_size.height - 3 } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod get_old_buffer { param($X = $this.pos.X, $Y = $this.pos.Y) $old_top = New-Object System.Management.Automation.Host.Coordinates 0, $Y $old_bottom = New-Object System.Management.Automation.Host.Coordinates $Host.ui.RawUI.BufferSize.Width, ($Y + $this.ui_size.height) $old_buffer = $Host.UI.RawUI.GetBufferContents((New-Object System.Management.Automation.Host.Rectangle $old_top, $old_bottom)) $this.old_menu_buffer = $old_buffer # 之前的内容 $this.old_menu_pos = $old_top # 之前的位置 } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod new_buffer { param($offset = 0) if ($PSCompletions.config.menu_list_cover_buffer) { $box = @() 0..$this.ui_size.Height | ForEach-Object { $box += (' ' * $Host.UI.RawUI.BufferSize.Width) } $pos = @{ X = 0 Y = $this.pos.Y } if ($PSCompletions.menu.is_show_above) { $pos.Y -- } $buffer = $Host.UI.RawUI.NewBufferCellArray($box, $host.UI.RawUI.BackgroundColor, $host.UI.RawUI.BackgroundColor) $Host.UI.RawUI.SetBufferContents($pos, $buffer) } $border_box = @() $content_box = @() $line_top = [string]$PSCompletions.config.menu_line_top_left + $PSCompletions.config.menu_line_horizontal * ($this.list_max_width + $PSCompletions.config.menu_list_margin_left + $PSCompletions.config.menu_list_margin_right) + $PSCompletions.config.menu_line_top_right $border_box += $line_top $offset..($this.ui_size.height - 3 + $offset) | ForEach-Object { $content = $this.filter_list[$_].name $border_box += [string]$PSCompletions.config.menu_line_vertical + (' ' * ($PSCompletions.config.menu_list_margin_left + $content.Length + $PSCompletions.config.menu_list_margin_right)) + [string]$PSCompletions.config.menu_line_vertical $content_box += (' ' * $PSCompletions.config.menu_list_margin_left) + $content + (' ' * $PSCompletions.config.menu_list_margin_right) } $status = "$(([string]($this.selected_index + 1)).PadLeft($this.filter_list.Count.ToString().Length, ' '))" $line_bottom = [string]$PSCompletions.config.menu_line_bottom_left + $PSCompletions.config.menu_line_horizontal + ' ' * ($status.Length + 1) + $PSCompletions.config.menu_line_horizontal * ($this.list_max_width + $PSCompletions.config.menu_list_margin_left + $PSCompletions.config.menu_list_margin_right - $status.Length - 2) + $PSCompletions.config.menu_line_bottom_right $border_box += $line_bottom $buffer = $Host.UI.RawUI.NewBufferCellArray($border_box, $PSCompletions.config.menu_color_border_text, $PSCompletions.config.menu_color_border_back) $Host.UI.RawUI.SetBufferContents($this.pos, $buffer) $buffer = $Host.UI.RawUI.NewBufferCellArray($content_box, $PSCompletions.config.menu_color_item_text, $PSCompletions.config.menu_color_item_back) $pos = @{ X = $this.pos.X + 1 Y = $this.pos.Y + 1 } $Host.UI.RawUI.SetBufferContents($pos, $buffer) } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod new_list_buffer { param($offset = 0) $content_box = @() $offset..($this.ui_size.height - 3 + $offset) | ForEach-Object { $content = $this.filter_list[$_].name $content_box += (' ' * $PSCompletions.config.menu_list_margin_left) + $content + (' ' * $PSCompletions.config.menu_list_margin_right) } $buffer = $Host.UI.RawUI.NewBufferCellArray($content_box, $PSCompletions.config.menu_color_item_text, $PSCompletions.config.menu_color_item_back) $pos = @{ X = $this.pos.X + 1 Y = $this.pos.Y + 1 } $Host.UI.RawUI.SetBufferContents($pos, $buffer) } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod new_filter_buffer { param($filter) if ($this.old_filter_buffer) { $Host.UI.RawUI.SetBufferContents($this.old_filter_pos, $this.old_filter_buffer) } $X = $this.pos.X $Y = $this.pos.Y $old_top = New-Object System.Management.Automation.Host.Coordinates $X, $Y $old_bottom = New-Object System.Management.Automation.Host.Coordinates $Host.ui.RawUI.BufferSize.Width, $Y $old_buffer = $Host.UI.RawUI.GetBufferContents((New-Object System.Management.Automation.Host.Rectangle $old_top, $old_bottom)) $this.old_filter_buffer = $old_buffer # 之前的内容 $this.old_filter_pos = $old_top # 之前的位置 $char = $PSCompletions.config.menu_filter_symbol $mindle = [System.Math]::Ceiling($char.Length / 2) $start = $char.Substring(0, $mindle) $end = $char.Substring($mindle) $buffer_filter = $Host.UI.RawUI.NewBufferCellArray(@(@($start, $filter, $end) -join ''), $PSCompletions.config.menu_color_filter_text, $PSCompletions.config.menu_color_filter_back) $pos_filter = $Host.UI.RawUI.CursorPosition $pos_filter.X = $this.pos.X + 2 $pos_filter.Y = $this.pos.Y $Host.UI.RawUI.SetBufferContents($pos_filter, $buffer_filter) } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod new_status_buffer { param($current = 1) if ($this.old_status_buffer) { $Host.UI.RawUI.SetBufferContents($this.old_status_pos, $this.old_status_buffer) } $X = $this.pos.X $Y = $this.pos.Y + $this.ui_size.height - 1 $old_top = New-Object System.Management.Automation.Host.Coordinates $X, $Y $old_bottom = New-Object System.Management.Automation.Host.Coordinates $Host.ui.RawUI.BufferSize.Width, ($Y + 1) $old_buffer = $Host.UI.RawUI.GetBufferContents((New-Object System.Management.Automation.Host.Rectangle $old_top, $old_bottom)) $this.old_status_buffer = $old_buffer # 之前的内容 $this.old_status_pos = $old_top # 之前的位置 $current = "$(([string]($this.selected_index + 1)).PadLeft($this.filter_list.Count.ToString().Length, ' '))" $buffer_status = $Host.UI.RawUI.NewBufferCellArray(@("$($current) $($PSCompletions.config.menu_status_symbol) $($PSCompletions.menu.filter_list.Count) "), $PSCompletions.config.menu_color_status_text, $PSCompletions.config.menu_color_status_back) $pos_status = $Host.UI.RawUI.CursorPosition $pos_status.X = $this.pos.X + 3 $pos_status.Y = $this.pos.Y + $this.ui_size.height - 1 $Host.UI.RawUI.SetBufferContents($pos_status, $buffer_status) } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod get_old_tip_buffer { param($X = $this.pos_tip.X, $Y = $this.pos_tip.Y) if ($PSCompletions.config.menu_tip_cover_buffer) { if ($PSCompletions.menu.is_show_above) { $Y = 0 $to_Y = $this.pos.Y } else { $Y = $this.pos_tip.Y - 1 $to_Y = $Host.UI.RawUI.BufferSize.Height } } else { if ($PSCompletions.menu.is_show_above) { $Y = $this.pos_tip.Y - 1 $to_Y = $this.pos.Y } else { $Y = $this.pos_tip.Y - 1 $to_Y = $this.pos_tip.Y + $this.tip_max_height } } $old_top = New-Object System.Management.Automation.Host.Coordinates 0, $Y $old_bottom = New-Object System.Management.Automation.Host.Coordinates $Host.ui.RawUI.BufferSize.Width, $to_Y $old_buffer = $Host.UI.RawUI.GetBufferContents((New-Object System.Management.Automation.Host.Rectangle $old_top, $old_bottom)) $this.old_tip_buffer = $old_buffer $this.old_tip_pos = $old_top } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod new_tip_buffer { param($index = 0) $box = @() if ($PSCompletions.config.menu_tip_cover_buffer) { if ($PSCompletions.menu.is_show_above) { 0..($this.pos.Y - 1) | ForEach-Object { $box += (' ' * $Host.UI.RawUI.BufferSize.Width) } $pos = @{ X = 0 Y = 0 } } else { 0..($Host.UI.RawUI.BufferSize.Height - $this.pos_tip.Y) | ForEach-Object { $box += (' ' * $Host.UI.RawUI.BufferSize.Width) } $pos = @{ X = 0 Y = $this.pos_tip.Y - 1 } } } else { 0..($this.tip_max_height + 1) | ForEach-Object { $box += (' ' * $Host.UI.RawUI.BufferSize.Width) } $pos = @{ X = 0 Y = $this.pos_tip.Y - 1 } if ($PSCompletions.menu.is_show_above -and $pos.Y -lt 0) { $pos.Y = 0 } } $buffer = $Host.UI.RawUI.NewBufferCellArray($box, $host.UI.RawUI.BackgroundColor, $host.UI.RawUI.BackgroundColor) $Host.UI.RawUI.SetBufferContents($pos, $buffer) $box = @() function _do($string, $max_width, $is_cut) { $width = $this.get_length($string) if ($is_cut) { if ($width -le $max_width - 3) { return "$($string)..." } } else { if ($width -le $max_width) { return $string } } _do $string.Substring(0, ($string.Length - 2)) $max_width $true } $this.filter_list[$index].tip -split "`n" | ForEach-Object { if ($_) { $box += _do $_ ($Host.UI.RawUI.BufferSize.Width - 1) } } if ($box) { $pos = @{ X = $this.pos_tip.X Y = $this.pos_tip.Y } $buffer = $Host.UI.RawUI.NewBufferCellArray($box, $PSCompletions.config.menu_color_tip_text, $PSCompletions.config.menu_color_tip_back) $Host.UI.RawUI.SetBufferContents($pos, $buffer) } } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod set_selection { param($offset = $this.page_current_index) if ($this.old_selection) { $Host.UI.RawUI.SetBufferContents($this.old_selection.pos, $this.old_selection.buffer) } # 如果高亮需要包含 margin if ($PSCompletions.config.menu_selection_with_margin) { $X = $this.pos.X + 1 $to_X = $X + $this.list_max_width - 1 + $PSCompletions.config.menu_list_margin_left + $PSCompletions.config.menu_list_margin_right } else { $X = $this.pos.X + 1 + $PSCompletions.config.menu_list_margin_left $to_X = $X + $this.list_max_width - 1 } # 当前页的第几个 $Y = $this.pos.Y + 1 + $offset # 根据坐标,生成需要被改变内容的矩形,也就是要被选中的项 $Rectangle = New-Object System.Management.Automation.Host.Rectangle $X, $Y, $to_X, $Y # 通过矩形,获取到这个矩形中的原本的内容 $LineBuffer = $Host.UI.RawUI.GetBufferContents($Rectangle) $this.old_selection = @{ pos = @{ X = $X Y = $Y } buffer = $LineBuffer } # 给原本的内容设置颜色和背景颜色 $LineBuffer = $Host.UI.RawUI.NewBufferCellArray( @([string]::Join('', ($LineBuffer | .{ process { $_.Character } }))), $PSCompletions.config.menu_color_selected_text, $PSCompletions.config.menu_color_selected_back ) $Host.UI.RawUI.SetBufferContents(@{ X = $X; Y = $Y }, $LineBuffer) } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod move_selection { param([int]$count) $is_scroll = $false $is_move = $false if ($this.selected_index + $count -ge 0 -and $this.selected_index + $count -le ($this.filter_list.Count - 1) ) { if ($count -gt 0) { if ($this.page_current_index -ge $this.page_max_index) { $is_scroll = $true } else { $is_move = $true } } else { if ($this.page_current_index -le 0) { $is_scroll = $true } else { $is_move = $true } } } if ($is_move) { $this.page_current_index += $count $this.selected_index += $count $this.set_selection() } if ($is_scroll) { $this.selected_index += $count $this.offset += $count $this.new_list_buffer($this.offset) $this.old_selection = $null $this.set_selection() } } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod get_prefix { $prefix = $this.filter_list[-1].value for ($i = $this.filter_list.count - 2; $i -ge 0 -and $prefix; --$i) { $text = $this.filter_list[$i].value if ($text) { while ($prefix -and !$text.StartsWith($prefix, [StringComparison]::OrdinalIgnoreCase)) { $prefix = $prefix.Substring(0, $prefix.Length - 1) } } } $this.filter = $this.filter_by_auto_pick = $prefix } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod filter_completions { param($filter_list) # 如果是前缀匹配 if ($PSCompletions.config.menu_is_prefix_match) { $match = "$($this.filter)*" } else { $match = "*$($this.filter)*" } $this.filter_list = $filter_list | Where-Object { $_.name -like $match } | Where-Object { $_.name -ne '' } if ($this.filter_list -is [array]) { $PSCompletions.is_single = $false } else { $PSCompletions.is_single = $true $this.filter_list = @($this.filter_list) } } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod reset { param($clearAll) # reset content try { $Host.UI.RawUI.SetBufferContents($this.old_tip_pos, $this.old_tip_buffer) if ($clearAll) { $this.old_tip_buffer = $null $this.old_tip_pos = $null } } catch {} try { $Host.UI.RawUI.SetBufferContents($this.old_menu_pos, $this.old_menu_buffer) if ($clearAll) { $this.old_menu_buffer = $null $this.old_menu_pos = $null } } catch {} $this.old_selection = $null $this.old_filter_buffer = $null $this.old_filter_pos = $null $this.old_status_buffer = $null $this.old_status_pos = $null $this.offset = 0 $this.selected_index = 0 $this.page_current_index = 0 $menu_show_tip = $PSCompletions.config.comp_config.$($PSCompletions.current_cmd).menu_show_tip if ($menu_show_tip) { $this.is_show_tip = $menu_show_tip -eq 1 } else { $this.is_show_tip = $PSCompletions.config.menu_show_tip -eq 1 } } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod show_module_menu { param($filter_list) $this.origin_filter_list = $this.filter_list = $filter_list $lastest_encoding = [console]::OutputEncoding [console]::OutputEncoding = $PSCompletions.encoding $this.pos = $Host.UI.RawUI.WindowPosition $this.pos_tip = $Host.UI.RawUI.WindowPosition $this.list_max_width = 0 $this.ui_size = $Host.UI.RawUI.BufferSize $this.filter = '' # 过滤的关键词 $this.old_filter = '' $this.page_current_index = 0 # 当前显示第几个 $this.selected_index = 0 # 当前选中的索引 $this.old_selected_index = 0 $this.offset = 0 # 索引的偏移量,用于滚动翻页 $this.filter_completions($this.origin_filter_list) # 如果没有可用的选项,直接结束,触发路径补全 if (!$this.filter_list) { return } $this.handle_list() if ($PSCompletions.config.enter_when_single -and $PSCompletions.is_single) { return $this.filter_list[$this.selected_index].value } $this.parse_list() # 如果解析后的菜单高度小于 3 (上下边框 + 1个补全项) if ($this.ui_size.Height -lt 3 -or $this.ui_size.Width -gt $Host.ui.RawUI.BufferSize.Width - 2) { [Microsoft.PowerShell.PSConsoleReadLine]::UndoAll() [Microsoft.PowerShell.PSConsoleReadLine]::Insert($PSCompletions.info.min_area) '' return } # 第一次显示菜单之前,记录之前的 buffer 内容 $this.get_old_buffer() if ($this.is_show_tip) { $this.get_old_tip_buffer() } # 显示菜单 $this.new_buffer($this.offset) if ($this.is_show_tip) { $this.new_tip_buffer($this.selected_index) } if ($PSCompletions.config.menu_is_prefix_match) { $this.get_prefix() } $this.new_filter_buffer($this.filter) $this.new_status_buffer() $this.set_selection() try { :loop while (($PressKey = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown,AllowCtrlC')).VirtualKeyCode) { $shift_pressed = 0x10 -band [int]$PressKey.ControlKeyState if ($PressKey.ControlKeyState -like "*CtrlPressed*") { switch ($PressKey.VirtualKeyCode) { 67 { # Ctrl + c $this.reset($true) '' break loop } { $_ -eq 85 -or $_ -eq 80 } { # 85: Ctrl + u # 80: Ctrl + p $this.move_selection(-1) break } { $_ -eq 68 -or $_ -eq 78 } { # 68: Ctrl + d # 78: Ctrl + n $this.move_selection(1) break } } } switch ($PressKey.VirtualKeyCode) { { $_ -in @(9, 32) } { # Tab or Space if ($PSCompletions.is_single) { $this.reset($true) $this.filter_list[$this.selected_index].value break loop } if ($shift_pressed) { # Up $this.move_selection(-1) } else { # Down $this.move_selection(1) } break } 27 { # ESC $this.reset($true) '' break loop } 13 { # Enter $this.filter_list[$this.selected_index].value $this.reset($true) break loop } ### 向上(Up/Left) { $_ -in @(37, 38) } { $this.move_selection(-1) break } ### 向下(Down/Right) { $_ -in @(39, 40) } { $this.move_selection(1) break } ### Character/Backspace { $PressKey.Character } { # update filter $this.old_filter = $this.filter $old_filter_list = $this.filter_list if ($PressKey.Character -eq 8) { # backspace if ($this.filter -eq $this.filter_by_auto_pick) { $this.filter = '' $this.filter_by_auto_pick = '' $this.reset($true) '' break loop } if ($this.filter) { $this.filter = $this.filter.Substring(0, $this.filter.Length - 1) } else { $this.reset($true) '' break loop } $this.reset() $this.filter_completions($this.origin_filter_list) $this.handle_list() $this.parse_list() $this.new_buffer($this.offset) if ($this.is_show_tip) { $this.new_tip_buffer($this.selected_index) } $this.new_filter_buffer() $this.new_status_buffer() $this.set_selection(0) } else { # add char $this.filter += $PressKey.Character $this.filter_completions($this.filter_list) if (!$this.filter_list) { $this.filter = $this.old_filter $this.filter_list = $old_filter_list } else { $this.reset() $this.parse_list() $this.new_buffer($this.offset) if ($this.is_show_tip) { $this.new_tip_buffer($this.selected_index) } $this.new_filter_buffer() $this.new_status_buffer() $this.set_selection(0) } } break } } if ($this.selected_index -ne $this.old_selected_index) { $this.new_status_buffer() if ($this.is_show_tip) { $this.new_tip_buffer($this.selected_index) } $this.old_selected_index = $this.selected_index } if ($this.filter -ne $this.old_filter) { $this.new_filter_buffer($this.filter) $this.old_filter = $this.filter } } } catch { $this.reset($true) } [console]::OutputEncoding = $lastest_encoding } Add-Member -InputObject $PSCompletions.menu -MemberType ScriptMethod show_powershell_menu { param($filter_list) if ($Host.UI.RawUI.BufferSize.Height -lt 5) { [Microsoft.PowerShell.PSConsoleReadLine]::UndoAll() [Microsoft.PowerShell.PSConsoleReadLine]::Insert($PSCompletions.info.min_area) '' return } $json = $PSCompletions.data.$($PSCompletions.current_cmd) $info = $json.info $max_width = 0 $tip_max_height = 0 $filter_list = $filter_list | ForEach-Object { $symbol = ($PSCompletions.replace_content($_.symbol, ' ') -split ' ' | ForEach-Object { $PSCompletions.config."symbol_$($_)" }) -join '' $pad = if ($symbol) { "$($PSCompletions.config.menu_between_item_and_symbol)$($symbol)" }else { '' } $name_with_symbol = "$($_.name[-1])$($pad)" $width = $this.get_length($name_with_symbol) if ($width -gt $max_width) { $max_width = $width } if ($_.tip) { $tip = $PSCompletions.replace_content($_.tip) $tip_arr = $tip -split "`n" } else { $tip_arr = @() } if ($tip_arr.Count -gt $tip_max_height) { $tip_max_height = $tip_arr.Count } @{ name = $name_with_symbol value = $_.name[-1] width = $width tip = $tip } } $item_witdh = $max_width + 2 $ui_max_width = 100 $ui_width = if ($Host.UI.RawUI.BufferSize.Width -gt $ui_max_width) { $ui_max_width }else { $Host.UI.RawUI.BufferSize.Width } $max_count = ($Host.UI.RawUI.BufferSize.Height - $tip_max_height) * ([math]::Floor($ui_width) / ($item_witdh)) $display_count = 0 if ($max_count -lt 5 -or !$PSCompletions.config.menu_show_tip) { $max_count = ($Host.UI.RawUI.BufferSize.Height) * ([math]::Floor($ui_width) / ($item_witdh)) $filter_list | ForEach-Object { if ($max_count -gt $display_count -and $_.name) { $display_count++ [CompletionResult]::new($_.value, $_.name, 'ParameterValue', ' ') } } } else { $filter_list | ForEach-Object { if ($max_count -gt $display_count -and $_.name) { $display_count++ [CompletionResult]::new($_.value, $_.name, 'ParameterValue', $_.tip) } } } if ($filter_list -is [array] -and $display_count -lt $filter_list.Count) { [CompletionResult]::new(' ', '...', 'ParameterValue', $PSCompletions.info.comp_hide) $display_count++ } if ($display_count -eq 1 -and !$PSCompletions.config.enter_when_single) { ' ' } } |