-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: support compound file-types #3145
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -22,6 +22,21 @@ M.default_config = { | |||||||
-- global on_setup hook | ||||||||
M.on_setup = nil | ||||||||
|
||||||||
---@param filetype string the filetype to check (can be a compound, dot-separated filetype; see |'filetype'|) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this new function has no docstring explaining its purpose. and this PR has a wall of text discussing it. how in the world is anyone supposed know when to use this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. apologies, I didn't realize that it was unclear. I've added documentation. let me know if it's unclear There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doesn't look like there is a summary docstring. also a couple input => output examples would go a long way.
|
||||||||
---@param expected string|string[] the filetype(s) to match against | ||||||||
---@return boolean | ||||||||
function M.ft_matches(filetype, expected) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there has vim.fs module. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, can you explain? I don't see anything in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. okay see vim.filetype moudle. vim.filetype.match will return the filetype if it already in default detect table or register by vim.filetype.add . we don't want add more utils function now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
*'filetype'* *'ft'*
'filetype' 'ft' string (default "")
local to buffer |local-noglobal|
...
Setting this option to a different value is most useful in a modeline,
for a file for which the file type is not automatically recognized.
Example, for in an IDL file: >c
/* vim: set filetype=idl : */
< |FileType| |filetypes|
When a dot appears in the value then this separates two filetype
names. Example: >c
/* vim: set filetype=c.doxygen : */
< This will use the "c" filetype first, then the "doxygen" filetype.
This works both for filetype plugins and for syntax files. More than
one dot may appear.
This option is not copied to another buffer, independent of the 's' or
'S' flag in 'cpoptions'.
Only normal file name characters can be used, `/\*?[|<>` are illegal. In other words: local ft = vim.filetype.match({buf=0})
ft == "c.doxygen"
util.ft_matches(ft, 'idl') == false
util.ft_matches(ft, 'c') == true
util.ft_matches(ft, 'doxygen') == true There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can also pass filename into match -- Using a filename without a buffer
vim.filetype.match({ filename = 'main.lua' })
-- Using file contents
vim.filetype.match({ contents = {'#!/usr/bin/env bash'} }) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, i.e. local ft = vim.filetype.match({ filename = 'main.lua' })
ft == "lua"
local filetypes_supported_by_current_client = { "lua", "sh", "c" }
util.ft_matches(ft, filetypes_supported_by_current_client) == true Usually this would just be a local ft = vim.bo.filetype
ft == "yaml.ansible" -- this is not a filename! it is a _compound_ filetype
util.ft_matches(ft, "ansible") == true
util.ft_matches(ft, "yaml") == true notice that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for your kind reply . does register a filetype by using vim.filetype.add for a special file not make sense in user side ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A completely unique type is not desirable because we want to use the existing behaviors defined for the primary filetype. see mfussenegger/nvim-ansible or pearofducks/ansible-vim. They both You want ansible scripts to have the yaml filetype because that's what they are; we want (neo)vim to keep recognizing them as yaml files. if we set But the plugin additionally sets various useful options like The problem is that right now, nvim-lspconfig diverges from standard vim behavior because filetype matching operates on the entire nvim-lspconfig/lua/lspconfig/server_configurations/yamlls.lua Lines 4 to 6 in a3d9395
(notice that With this change, you can instead just specify |
||||||||
expected = type(expected) == 'table' and expected or { expected } | ||||||||
for ft in filetype:gmatch '([^.]+)' do | ||||||||
for _, expected_ft in ipairs(expected) do | ||||||||
if ft == expected_ft then | ||||||||
return true | ||||||||
end | ||||||||
end | ||||||||
end | ||||||||
return false | ||||||||
end | ||||||||
|
||||||||
function M.bufname_valid(bufname) | ||||||||
if bufname:match '^/' or bufname:match '^[a-zA-Z]:' or bufname:match '^zipfile://' or bufname:match '^tarfile:' then | ||||||||
return true | ||||||||
|
@@ -348,10 +363,8 @@ function M.get_active_clients_list_by_ft(filetype) | |||||||
local clients_list = {} | ||||||||
for _, client in pairs(clients) do | ||||||||
local filetypes = client.config.filetypes or {} | ||||||||
for _, ft in pairs(filetypes) do | ||||||||
if ft == filetype then | ||||||||
table.insert(clients_list, client.name) | ||||||||
end | ||||||||
if M.ft_matches(filetype, filetypes) then | ||||||||
table.insert(clients_list, client.name) | ||||||||
end | ||||||||
end | ||||||||
return clients_list | ||||||||
|
@@ -364,10 +377,8 @@ function M.get_other_matching_providers(filetype) | |||||||
for _, config in pairs(configs) do | ||||||||
if not vim.tbl_contains(active_clients_list, config.name) then | ||||||||
local filetypes = config.filetypes or {} | ||||||||
for _, ft in pairs(filetypes) do | ||||||||
if ft == filetype then | ||||||||
table.insert(other_matching_configs, config) | ||||||||
end | ||||||||
if M.ft_matches(filetype, filetypes) then | ||||||||
table.insert(other_matching_configs, config) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these changes seem like they might be useful, but configs themselves can use vim.filetype.match() as shown in #3145 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See: concerns raised in #3145 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even so, it's not acceptable to introduce another public API to lspconfig, we are trying to shrink it and upstream its API to Nvim core so that lspconfig is mostly "data-only". I also strongly suspect that configs themselves don't need this new API. |
||||||||
end | ||||||||
end | ||||||||
end | ||||||||
|
@@ -379,10 +390,8 @@ function M.get_config_by_ft(filetype) | |||||||
local matching_configs = {} | ||||||||
for _, config in pairs(configs) do | ||||||||
local filetypes = config.filetypes or {} | ||||||||
for _, ft in pairs(filetypes) do | ||||||||
if ft == filetype then | ||||||||
table.insert(matching_configs, config) | ||||||||
end | ||||||||
if M.ft_matches(filetype, filetypes) then | ||||||||
table.insert(matching_configs, config) | ||||||||
end | ||||||||
end | ||||||||
return matching_configs | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why can't we use vim.filetype.match with the
fname
, here? (note: the parens in the code below are important because match() has multi-value return)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Been a while since I looked at this code, but I think that should work. I just didn't want to change the semantics of the existing code. e.g. your suggested check wouldn't match files with a manually set
filetype
; although I'm not sure if that is a negligible difference or not. Would lspconfig even spawn a server for e.g.foobar.txt
where the user calls:set filetype=elm
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case, and in retrospect, I think this check could have be simplified down to:
since
util.ft_matches(filetype, 'elm')
should match bothelm
andelm.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
upon further thinking, I think
vim.filetype.match
will also fail whenfiletype
is set via autocmd rather thanfiletype.lua
. e.g. if we follow the suggestion from the sixtyfps server config:nvim-lspconfig/lua/lspconfig/configs/sixtyfps.lua
Lines 17 to 23 in aa615f6
opening
foo.60
will setfiletype
tosixtyfps
butvim.filetype.match({filename=fname})
will returnnil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see #3145 (comment)