{"id":13477399,"url":"https://github.com/garyhurtz/cmp_kitty","last_synced_at":"2025-03-27T05:31:31.886Z","repository":{"id":144398861,"uuid":"609986149","full_name":"garyhurtz/cmp_kitty","owner":"garyhurtz","description":"Kitty completion source for nvim-cmp","archived":false,"fork":false,"pushed_at":"2024-05-18T15:32:06.000Z","size":147,"stargazers_count":52,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-30T10:40:19.626Z","etag":null,"topics":["kitty","kitty-terminal","neovim","nvim-cmp"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garyhurtz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-05T20:16:54.000Z","updated_at":"2024-09-17T08:38:30.000Z","dependencies_parsed_at":"2024-01-13T19:18:56.695Z","dependency_job_id":"6615788c-debc-48e1-900e-a179bedbd078","html_url":"https://github.com/garyhurtz/cmp_kitty","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyhurtz%2Fcmp_kitty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyhurtz%2Fcmp_kitty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyhurtz%2Fcmp_kitty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyhurtz%2Fcmp_kitty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garyhurtz","download_url":"https://codeload.github.com/garyhurtz/cmp_kitty/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245791540,"owners_count":20672666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kitty","kitty-terminal","neovim","nvim-cmp"],"created_at":"2024-07-31T16:01:42.237Z","updated_at":"2025-03-27T05:31:31.380Z","avatar_url":"https://github.com/garyhurtz.png","language":"Lua","readme":"# cmp_kitty\n\nKitty completion source for [nvim-cmp](https://github.com/hrsh7th/nvim-cmp).\n\nThis extension extracts content from Kitty windows and makes it available in nvim-cmp completions.\nA wide range of configuration options provide control over the types of information to extract,\nas well as which tabs and windows contribute completions.\n\n## Motivation / use case\n\nWhen working on a project one often has several Kitty windows open containing different types of\ninformation from different sources. For example, one tab might contain windows containing Neovim,\ntest output, and a command line, while another tab might contain other project-related content.\n\nThis extension pulls content from each of the tabs and windows and makes it available in Neovim\nvia completions, which provides a bit of integration between the different tools.\n\nExample use cases:\n\n1. While developing a Flask application, one often needs to reference view *endpoints*. While one\n   could create a custom completion source containing endpoints for each project, this can be\nachieved automatically with *cmp-kitty*; Simply create a new Kitty window, run `flask routes`, which\nlists all project endpoints in that window. After jumping back to the original window all project\nendpoints appear as completion candidates.\n\n1. While working on front-end development one often has both HTML and javascript files open, with a\n   javascript file referencing *ids*, *classes*, etc in the HTML. *cmp-kitty* automatically parses\nthis content from the HTML window and makes it available in the javascript window (and vice versa),\nallowing auto-completion that automatically updates as the project develops.\n\n1. One can access a specific filename in Neovim by jumping to a new Kitty window, cd'ing into\nthe directory containing the file, then running ls. After jumping back to Neovim the filename appears\nin the completions.\n\n## Requirements\n\n- [Neovim](https://github.com/neovim/neovim/)\n- [nvim-cmp](https://github.com/hrsh7th/nvim-cmp)\n- [Kitty](https://github.com/kovidgoyal/kitty)\n\n### Kitty configuration\n\nThis extension requires configuring Kitty to enable remote control. Refer to the\n[Kitty documentation](https://sw.kovidgoyal.net/kitty/remote-control) for detailed information\nabout how to do this.\n\nIn short, set the *allow_remote_control* line of your *kitty.conf* file to one of:\n\n    allow_remote_control socket-only\n    allow_remote_control socket\n    allow_remote_control yes\n\nNext, follow [the instructions](https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.listen_on) for setting\nthe socket that Kitty uses for communication.\n\nOnce configured you can test the Kitty configuration from the command line by opening a separate\nterminal and executing a command such as:\n\n    kitty @ ls\n\nwhich returns a JSON response when Kitty has been configured correctly.\n\nAfter configuring Kitty, then install this extension.\n\n## Installation and setup\n\nUse your package manager of choice. For example [packer.nvim](https://github.com/wbthomason/packer.nvim):\n\n```lua\nuse {\n  'garyhurtz/cmp_kitty',\n    config = function()\n        require('cmp_kitty'):setup()\n    end\n}\n\n```\n\nthen\n\n```lua\nrequire('cmp').setup({\n  sources = {\n    { name = 'kitty'\n        option = {\n            -- this is where any configuration should be inserted\n        }\n    }\n  }\n})\n```\n\n\nIf you use [lazy.nvim](https://github.com/folke/lazy.nvim) the setup would be something like this:\n\n```lua\nrequire(\"lazy\").setup({\n    {\n        \"hrsh7th/nvim-cmp\",\n        opts = {\n            completion = {\n                ...\n            },\n            sources = {\n                ...\n                {\n                    name = \"kitty\",\n                    option = {\n                        -- this is where any configuration should be inserted\n                    },\n                },\n            },\n        },\n    },\n    {\n        \"garyhurtz/cmp_kitty\",\n        dependencies = {\n            { \"hrsh7th/nvim-cmp\" },\n        },\n        init = function()\n            require('cmp_kitty'):setup()\n        end\n    },\n})\n```\n\nTo check your installation you can test communication between *cmp_kitty* and Kitty itself with the command:\n\n    :CmpKittyLs\n\nThis should open a new buffer and insert the contents of Kitty's JSON response, as it did from the\ncommand line.\n\nSee below for more information about this command.\n\n## Configuration\n\nConfiguration uses nvim-cmp's standard *option* table, as shown below. By default all tabs and windows contribute\ncompletions, and completions include most types of available information. Configure which information to\ninclude using the *match_* configuration options, below. You can find the bodies of the default functions\nin their respective sections of the documentation.\n\n```lua\noption = {\n\n    -- cmp configuration\n    trigger_characters = {},\n    trigger_characters_ft = {},\n    keyword_pattern = [[\\w\\+]],\n\n    -- what information to collect\n\n    --- words\n    match_words = true,\n    match_upper_case = false,\n    match_lower_case = false,\n    match_capitalized = false,\n    match_alphanumerics = true,\n    match_camel_case = true,\n    match_kebab_case = true,\n    match_snake_case = true,\n    match_dot_case = true,\n    match_words_with_punctuation = true,\n\n    --- numbers\n    match_integers = true,\n    match_floats = true,\n    match_hex_strings = true,\n    match_binary_strings = true,\n\n    --- computing\n    match_emails = true,\n    match_ip_addrs = true,\n    match_uuids = true,\n    match_aws_unique_id = false,\n\n    --- paths\n    match_urls = { \"https?\" },\n    match_directories = true,\n    match_files = true,\n    match_files_by_suffix = {},\n    match_hidden_files = true,\n\n    -- window matching configuration\n    os_window = {\n\n        include_focused = true,\n        include_unfocused = true,\n\n        include_active = true,\n        include_inactive = true,\n\n        tab = {\n\n            include_active = true,\n            include_inactive = true,\n\n            include_title = function,\n            exclude_title = function,\n\n            window = {\n\n                include_focused = true,\n                include_unfocused = true,\n\n                include_active = true,\n                include_inactive = true,\n\n                include_title = function,\n                exclude_title = function,\n\n                include_cwd = function,\n                exclude_cwd = function,\n\n                include_env = function,\n                exclude_env = function,\n\n                include_foreground_process = function,\n                exclude_foreground_process = function,\n            },\n        },\n    },\n\n    extent = \"all\",\n\n    strict_matching = true,\n\n    -- Timing configuration\n    window_polling_period = 100, -- in msec\n    completion_min_update_period = 5, -- in seconds\n    completion_item_lifetime = 60, -- in seconds\n}\n\n```\n\n## Content parsing configuration\n\nThis plugin supports parsing various types of information from Kitty window content:\n\n### Words\n\n- match_alphanumerics [default: true]\n\nMatch text consisting of only letters and digits, with at least one letter and one digit.\n\n- match_words [default: true]\n\nMatch anything consisting of only letters, case-insensitive.\n\n- match_upper_case [default: false]\n- match_lower_case [default: false]\n- match_capitalized [default: false]\n\nMatch text that consists of either all upper-case, all lower-case letters, or a single upper-case\nletter followed by lower-case letters, respectively.\n\nThese are *false* by default since they return subsets of *match_word*, which is *true* by default.\nTo enable case-sensitive word matching, set *match_words* to *false* then set one or more of these to *true*.\n\n- match_camel_case [default: true]\n\nMatch camel-case words, which are groups of two or more words with word boundaries designated by a\nsingle capital letter, rather than a space. For example, ThisIsCamelCase, and thisIsCamelCase. As\nshown in the examples, variations with either upper-case and lower-case first-letters are both\nsupported.\n\n- match_kebab_case [default: true]\n\nMatch kebab-case words, which are groups of two or more case-insensitive words with word boundaries\ndesignated by a single hyphen, rather than a space. For example, this-is-kebab-case.\n\n- match_snake_case [default: true]\n\nMatch snake-case words, which are groups of two or more case-insensitive words with word boundaries\ndesignated by a single underscore, rather than a space. For example, this_is_snake_case.\n\n- match_dot_case [default: true]\n\nMatch dot-case words, which are groups of two or more case-insensitive words with word boundaries\ndesignated by a single dot, rather than a space. For example, this.is.dot.case.\n\n- match_words_with_punctuation [default: true]\n\nLike *match_words*, but matches words followed by a single punctuation character, then returns the\nword without the punctuation.\n\n### Numbers\n\n- match_integers [default: true]\n\nMatch groups of text consisting of only digits, optionally with a leading + or -.\n\n- match_floats [default: true]\n\nMatch groups of text that contain only digits, followed by a dot, followed by more digits,\noptionally with a leading + or -.\n\n- match_hex_strings [default: true]\n\nMatch text consisting of only hexadecimal characters, optionally with a leading 0x or # prefix.\n\n- match_binary_strings [default: true]\n\nMatch text consisting of only 4 or more zeros and ones.\n\n### Computing\n\n- match_emails [default: true]\n\nMatch text that appears to be an email address.\n\n- match_ip_addrs [default: true]\n\nMatch text that appears to be an IP address.\n\n- match_uuids [default: true]\n\nMatch text that appears to be a UUID, optionally wrapped in brackets.\n\n- match_aws_unique_id default: false\n\nMatch text that appears to be an AWS Unique ID (Access Key ID, etc).\n\nThis is opt-in (defaults *false*) due to potential security implications.\n\n### Paths\n\n- match_urls [default: {\"https?\"}]\n\nMatch text that appears to be a URL using one of the specified schemes. Specify other schemes\nby adding them to the *match_urls* configuration table. Note that schemes specified in\nconfiguration replace the default rather than add to it.\n\n- match_directories [default: true]\n\nMatch text that appears to be a directory.\n\n- match_files [default: true]\n\nMatch text that appears to be a file, possibly within one or more directories.\n\n- match_hidden_files [default: true]\n\nMatch text that appears to be a hidden-file, possibly within one or more directories.\n\n- match_files_by_suffix [default: {}]\n\nA complementary and more liberal method of identifying files. By default this doesn't match any\nfiles. Add one or more suffixes to this table to identify file types that should match liberally.\nSpecify suffixes without the leading dot, using either strings or patterns.\n\n## Window matching configuration\n\nWindow-matching configuration provides control over which tabs and windows contribute completion\ncandidates. Matching follows the\n[Kitty hierarchy](https://sw.kovidgoyal.net/kitty/overview/#tabs-and-windows): OS-windows contain\none or more tabs, which each contain one or more windows, which each contain content. Following\nthis hierarchy, *cmp_kitty* evaluates OS-windows first, followed by any tabs contained within\nmatching OS-windows, then windows contained within matching tabs.\n\nConfiguration items for tab and window matching logic use the *include_* and *exclude_* prefixes,\nspecifying which tabs and windows to include and exclude, respectively. The high-level matching\nlogic is as follows:\n\n    match = any(*include_*) and not any(*exclude_*)\n\nIn other words, evaluate each tab and window according to each of the *include_* configuration items.\nIf any *include_* item returns True then include that window or tab *unless* any of the\n*exclude_* configuration items also returns True. In that case, ignore content from that window or tab.\nAs such, *exclude_* configuration items take precedence over *include_* items.\n\nThe details of the various configuration items follows.\n\n### include_active, include_inactive, include_focused, and include_unfocused\n\nThese evaluate OS-windows, tabs, and windows according to their states. By default each of\n*include_active*, *include_inactive*, *include_focused*, and *include_unfocused* are *true*.\nSet one or more of these to *false* to exclude content from tabs and windows in that state.\n\nThe [Kitty docs](https://sw.kovidgoyal.net/kitty/remote-control) define when tabs and windows are\neither active or focused:\n\n\u003e Active tabs are the tabs that are active in their parent OS window. There is only one focused tab\n\u003e and it is the tab to which keyboard events are delivered. If no tab is focused, the last focused\n\u003e tab is matched\n\u003e\n\u003e Active windows are the windows that are active in their parent tab. There is only one focused\n\u003e window and it is the window to which keyboard events are delivered. If no window is focused,\n\u003e the last focused window is matched.\n\n### include_title and exclude_title\n\nThese evaluate tabs and windows according to their titles. By default, *cmp-kitty* always includes\ncontent from tabs and windows titled *\"cmp-include\"*, and always excludes content from tabs and\nwindows titled *cmp-exclude*, regardless of state.\n\nThe [Kitty docs](https://sw.kovidgoyal.net/kitty/remote-control/) detail how to set tab and window\ntitles using scripts. This plugin includes a command that sets a window title to *cmp-exclude*:\n\n    :CmpKittyExcludeWindow\n\nSee the Commands section below for more details.\n\nThe default function bodies are:\n\n```lua\ninclude_title = function(title)\n    return title == \"cmp-include\"\nend\n\nexclude_title = function(title)\n    return title == \"cmp-exclude\"\nend,\n```\n\nImplement custom logic by replacing one or both of these functions with a custom function\nthat implements the desired logic. These functions should accept a single argument, the title of\nthe tab or window, and return *true* for tabs and windows to include and *false* for those to exclude.\n\n### include_cwd and exclude_cwd\n\nThese evaluate windows based on their current working directory. This can be useful if, for example,\nyou want to omit content from an entire project.\n\nThe default function bodies disable this feature:\n\n```lua\ninclude_cwd = function(path)\n    return false\nend\n\nexclude_cwd = function(path)\n    return false\nend,\n```\n\nTo enable this feature, replace one or both functions with functions that implement the desired\nlogic. These functions should accept a single argument, a string containing the path of the current\nworking directory, then return *true* to include the window or *false* to exclude it.\n\n### include_env and exclude_env\n\nThese evaluate windows based on their environment variables.\n\nThe default function bodies include windows that contain an environment variable called\n\"CMP_INCLUDE\" and exclude windows containing an environment variable called \"CMP_EXCLUDE\":\n\n```lua\ninclude_env = function(env)\n    return vim.tbl_contains(vim.tbl_keys(env), \"CMP_INCLUDE\")\nend\n\nexclude_env = function(env)\n    return vim.tbl_contains(vim.tbl_keys(env), \"CMP_EXCLUDE\")\nend,\n```\n\nTo implement custom logic, replace one or both of these functions with a custom function. This\nfunction should accept a table containing each window's environment variables, then return *true*\nto include the window, or *false* to exclude it.\n\n### include_foreground_process and exclude_foreground_process\n\nThese evaluate windows based on the processes running within them. The default function bodies\nprovide templates for implementing custom logic, but otherwise disable this feature:\n\n```lua\ninclude_foreground_process = function(process)\n    local match_cmd = function(cmd)\n        -- match the command here\n        return false\n    end\n\n    for _, cmd in ipairs(process.cmdline) do\n        if match_cmd(cmd) == true then\n            return true\n        end\n    end\n\n    return false\nend\n\nexclude_foreground_process = function(process)\n    local match_cmd = function(cmd)\n        -- match the command here\n        return false\n    end\n\n    for _, cmd in ipairs(process.cmdline) do\n        if match_cmd(cmd) == true then\n            return true\n        end\n    end\n\n    return false\nend,\n```\n\nKitty returns the processes running within each window as a list of one or more tables. The\ndefault implementations loop over this list, passing each table to the *match_cmd* function.\nEach table contains the following information:\n\n```lua\n{\n    cmd={string},\n    pid=int,\n    cwd=string\n}\n```\n\nImplement custom logic by replacing *match_cmd* with a function that accepts these tables as input,\nthen returns *true* for windows to include, or *false* for windows to exclude. A window\ncontributes completions if *match_cmd* returns *true* for any table in the list.\n\nBe sure to examine the *foreground_processes* section of the output of the *:CmpKittyLs* command\nto gain a better understanding of the inputs that these functions receive.\n\n### Extent\n\nKitty provides the ability to specify how much window content to include when collecting completion\ncandidates. The options are:\n\n* *all* - the default, include all window content including the scroll-back\n* *screen* - include only the currently visible content\n* *selection* - include only content the contained within the current selection\n\nSee the [kitty docs](https://sw.kovidgoyal.net/kitty/remote-control/#kitty-get-text) for\nmore information.\n\n### Strict matching\n\nnvim-cmp configuration provides control over the completions it suggests from each source, typically\nusing fuzzy-matching. If *cmp_kitty* returns too many completions, set *strict_matching* to *true*\nto restrict the completions that *cmp_kitty* returns to only those that match the current input.\n\n## Timing configuration\n\nA brief description of the plugin architecture can be helpful to understanding the timing configuration.\n*cmp_kitty* stores completion candidates in a cache, which provides a quick response when nvim-cmp\nrequests completions. In parallel, *cmp_kitty* starts an \"update cycle\" in the background, collecting\ncandidates from each window and adding them to the cache so that they become available as nvim-cmp\nrequests them.\n\nThe update cycle proceeds in several steps. In the first step *cmp_kitty* evaluates each tab and window\naccording to the current configuration to determine which windows should contribute completions.\nIn the second step, *cmp_kitty* processes one window every *window_polling_period* msec, in order to\nspread out the work of querying Kitty and parsing content, then adds any completion candidates to the\ncache. Reduce the polling period for more aggressive timing, or increase it as needed on slower machines.\nIn the third step of the update cycle *cmp_kitty* evaluates each item in the cache and removes those\nthat have been in the cache for longer than the *completion_item_lifetime*.\n\nFinally, the *min_update_restart_period* defines the minimum number of seconds that *cmp_kitty* should\nwait between update cycles. If nvim-cmp requests completions during this period it receives items from\nthe cache, as usual, but *cmp_kitty* won't start a new update cycle until the first time nvim-cmp\nrequests completions after this period expires.\n\n## Commands\n\n### :CmpKittyLs\n\nOpen a buffer containing the output of Kitty's *ls* command. This is useful when customizing matching\nlogic. Details about the information contained in the response are available in the\n[kitty docs](https://sw.kovidgoyal.net/kitty/remote-control/#kitty-ls).\n\n### :CmpKittyIncludeWindow\n\nDisplay choices then change the title of the selected window to \"cmp-include\". Note that this command\nonly works if *include_title* remains in the default setting.\n\n### :CmpKittyExcludeWindow\n\nDisplay choices then change the title of the selected window to \"cmp-exclude\". Note that this command\nonly works if *exclude_title* remains in the default setting. Note that completions from an excluded\nwindow will persist for *completion_item_lifetime*, as described in the *Timing configuration*\nsection.\n","funding_links":[],"categories":["Lua"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryhurtz%2Fcmp_kitty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaryhurtz%2Fcmp_kitty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryhurtz%2Fcmp_kitty/lists"}