From b13306e5cc6da855f77e02b37e807a4b7e32b761 Mon Sep 17 00:00:00 2001 From: Corentin Brunel Date: Fri, 16 Jul 2021 14:17:21 -0400 Subject: [PATCH] feat: add cursor layout (#878) * Add basic implementation of "cursor" layout strategy * Update cursor layout strategy to properly follow cursor * feat(cursor_layout): handle previewer * Refactor cursor layout code * Add cursor theme * Update readme * Improve cursor theme and layout documentation * [docgen] Update doc/telescope.txt skip-checks: true * Remove trailing whitespace * Fix issues related with neovim and plugin api changes * [docgen] Update doc/telescope.txt skip-checks: true * Allow preview width to be configured * [docgen] Update doc/telescope.txt skip-checks: true Co-authored-by: Github Actions Co-authored-by: cbrunel --- README.md | 1 + doc/telescope.txt | 37 ++++++++ lua/telescope/config.lua | 4 + lua/telescope/pickers/layout_strategies.lua | 93 +++++++++++++++++++++ lua/telescope/themes.lua | 38 +++++++++ 5 files changed, 173 insertions(+) diff --git a/README.md b/README.md index 41a59920e4..df7116f308 100644 --- a/README.md +++ b/README.md @@ -545,6 +545,7 @@ We have some built in themes but are looking for more cool options. | Themes | Description | |--------------------------|---------------------------------------------------------------------------------------------| | `themes.get_dropdown` | A list like centered list. [dropdown](https://i.imgur.com/SorAcXv.png) | +| `themes.get_cursor` | A cursor relative list. | | `themes.get_ivy` | Bottom panel overlay. [Ivy #771](https://github.com/nvim-telescope/telescope.nvim/pull/771) | To use a theme, simply append it to a built-in function: diff --git a/doc/telescope.txt b/doc/telescope.txt index d5727cf413..7bc2062e83 100644 --- a/doc/telescope.txt +++ b/doc/telescope.txt @@ -94,6 +94,9 @@ telescope.setup({opts}) *telescope.setup()* center = { preview_cutoff = 40 }, + cursor = { + preview_cutoff = 40 + }, height = 0.9, horizontal = { preview_cutoff = 120, @@ -912,6 +915,17 @@ themes.get_dropdown() *themes.get_dropdown()* +themes.get_cursor() *themes.get_cursor()* + Cursor style theme. + + Usage: + + `local builtin = require('telescope.builtin')` + `local themes = require('telescope.themes')` + `builtin.lsp_code_actions(themes.get_cursor())` + + + themes.get_ivy() *themes.get_ivy()* Ivy style theme. @@ -1034,6 +1048,29 @@ layout_strategies.center() *layout_strategies.center()* - preview_cutoff: When lines are less than this value, the preview will be disabled +layout_strategies.cursor() *layout_strategies.cursor()* + Cursor layout dynamically positioned below the cursor if possible. If there + is no place below the cursor it will be placed above. + + ┌──────────────────────────────────────────────────┐ + │ │ + │ █ │ + │ ┌──────────────┐┌─────────────────────┐ │ + │ │ Prompt ││ Preview │ │ + │ ├──────────────┤│ Preview │ │ + │ │ Result ││ Preview │ │ + │ │ Result ││ Preview │ │ + │ └──────────────┘└─────────────────────┘ │ + │ █ │ + │ │ + │ │ + │ │ + │ │ + │ │ + └──────────────────────────────────────────────────┘ + + + layout_strategies.vertical() *layout_strategies.vertical()* Vertical layout stacks the items on top of each other. Particularly useful with thinner windows. diff --git a/lua/telescope/config.lua b/lua/telescope/config.lua index 27edc6c7a3..4593f7f182 100644 --- a/lua/telescope/config.lua +++ b/lua/telescope/config.lua @@ -80,6 +80,10 @@ local layout_config_defaults = { center = { preview_cutoff = 40, }, + + cursor = { + preview_cutoff = 40, + } } local layout_config_description = string.format([[ diff --git a/lua/telescope/pickers/layout_strategies.lua b/lua/telescope/pickers/layout_strategies.lua index 56100c3742..ae1b06c71e 100644 --- a/lua/telescope/pickers/layout_strategies.lua +++ b/lua/telescope/pickers/layout_strategies.lua @@ -391,6 +391,99 @@ layout_strategies.center = make_documented_layout("center", vim.tbl_extend("erro } end) +--- Cursor layout dynamically positioned below the cursor if possible. +--- If there is no place below the cursor it will be placed above. +--- +---
+--- ┌──────────────────────────────────────────────────┐
+--- │                                                  │
+--- │   █                                              │
+--- │   ┌──────────────┐┌─────────────────────┐        │
+--- │   │    Prompt    ││      Preview        │        │
+--- │   ├──────────────┤│      Preview        │        │
+--- │   │    Result    ││      Preview        │        │
+--- │   │    Result    ││      Preview        │        │
+--- │   └──────────────┘└─────────────────────┘        │
+--- │                                         █        │
+--- │                                                  │
+--- │                                                  │
+--- │                                                  │
+--- │                                                  │
+--- │                                                  │
+--- └──────────────────────────────────────────────────┘
+--- 
+layout_strategies.cursor = make_documented_layout("cursor", vim.tbl_extend("error", shared_options, { + preview_width = { "Change the width of Telescope's preview window", "See |resolver.resolve_width()|", }, + preview_cutoff = "When columns are less than this value, the preview will be disabled", +}), function(self, max_columns, max_lines, layout_config) + local initial_options = p_window.get_initial_window_options(self) + local preview = initial_options.preview + local results = initial_options.results + local prompt = initial_options.prompt + + local height_opt = layout_config.height + local height = resolve.resolve_height(height_opt)(self, max_columns, max_lines) + + local width_opt = layout_config.width + local width = resolve.resolve_width(width_opt)(self, max_columns, max_lines) + + local max_width = (width > max_columns and max_columns or width) + + local bs = get_border_size(self) + + prompt.height = 1 + results.height = height + preview.height = results.height + prompt.height + bs + + if self.previewer and max_columns >= layout_config.preview_cutoff then + preview.width = resolve.resolve_width(if_nil(layout_config.preview_width, function(_, cols) + -- By default, previewer takes 2/3 of the layout + return 2 * math.floor(max_width / 3) + end))(self, max_width, max_lines) + else + preview.width = 0 + end + + prompt.width = max_width - preview.width + results.width = prompt.width + + local total_height = preview.height + (bs*2) + local total_width = prompt.width + (bs*2) + preview.width + bs + + local position = vim.api.nvim_win_get_position(0) + local top_left = { + line = vim.fn.winline() + position[1] + bs, + col = vim.fn.wincol() + position[2] + } + local bot_right = { + line = top_left.line + total_height - 1, + col = top_left.col + total_width - 1 + } + + if bot_right.line > max_lines then + -- position above current line + top_left.line = top_left.line - total_height - 1 + end + if bot_right.col >= max_columns then + -- cap to the right of the screen + top_left.col = max_columns - total_width + end + + prompt.line = top_left.line + results.line = prompt.line + bs + 1 + preview.line = prompt.line + + prompt.col = top_left.col + results.col = prompt.col + preview.col = results.col + (bs*2) + results.width + + return { + preview = self.previewer and preview.width > 0 and preview, + results = results, + prompt = prompt + } +end) + --- Vertical layout stacks the items on top of each other. --- Particularly useful with thinner windows. --- diff --git a/lua/telescope/themes.lua b/lua/telescope/themes.lua index 939f79aa5a..3b2036b0a8 100644 --- a/lua/telescope/themes.lua +++ b/lua/telescope/themes.lua @@ -58,6 +58,44 @@ function themes.get_dropdown(opts) return vim.tbl_deep_extend("force", theme_opts, opts) end +--- Cursor style theme. +---
+---
+--- Usage:
+---
+---     `local builtin = require('telescope.builtin')`
+---     `local themes = require('telescope.themes')`
+---     `builtin.lsp_code_actions(themes.get_cursor())`
+--- 
+function themes.get_cursor(opts) + opts = opts or {} + + local theme_opts = { + theme = 'cursor', + + sorting_strategy = 'ascending', + results_title = false, + layout_strategy = 'cursor', + layout_config = { + width = function(_, _, _) + return 80 + end, + + height = function(_, _, _) + return 6 + end, + }, + borderchars = { + { '─', '│', '─', '│', '╭', '╮', '╯', '╰'}, + prompt = {'─', '│', ' ', '│', '╭', '╮', '│', '│'}, + results = {'─', '│', '─', '│', '├', '┤', '╯', '╰'}, + preview = { '─', '│', '─', '│', '╭', '╮', '╯', '╰'}, + }, + } + + return vim.tbl_deep_extend('force', theme_opts, opts) +end + --- Ivy style theme. ---
 ---