JoosepAlviste / nvim-ts-context-commentstring

Neovim treesitter plugin for setting the commentstring based on the cursor location in a file.
MIT License
1.17k stars 35 forks source link

How to make it work with `typescriptreact` #41

Closed andrestone closed 2 years ago

andrestone commented 2 years ago

Hey!

I was wondering if there's a way to make this plugin work with the FileType set to typescriptreact. Changing FileType to tsx breaks my other plugins.

Cheers!

JoosepAlviste commented 2 years ago

Hey! It should work fine with the filetype of typescriptreact (that is even what the filetype is for me). The tsx refers to the treesitter language/parser. So, if you have the tsx parser installed, it should already work.

Could you share some more information about your configuration if it's not working for you?

andrestone commented 2 years ago

Sure, here is my init.lua and init.vim. I have removed the plug-in since it wasn't working, so you won't see it on my Plug commands.

local sumneko_root_path = "/opt/homebrew/Cellar/lua-language-server/2.6.7/libexec"
local sumneko_binary = sumneko_root_path .. "/bin/lua-language-server"
local feedkey = function(key, mode)
  vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
local has_words_before = function()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end

local cmp = require("cmp")

cmp.setup({
    preselect = "item",
    snippet = {
        expand = function(args)
            vim.fn["vsnip#anonymous"](args.body)
        end,
    },
    mapping = {
        ["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
        ["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
        ["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
        ["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
        ["<C-f>"] = cmp.mapping.scroll_docs(-4),
        ["<C-d>"] = cmp.mapping.scroll_docs(4),
        ["<C-Space>"] = cmp.mapping.complete(),
        ["<C-e>"] = cmp.mapping.close(),
        -- ["<Tab>"] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "s" }),
        -- ["<S-Tab>"] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "s" }),
        ["<CR>"] = cmp.mapping.confirm({
            behavior = cmp.ConfirmBehavior.Replace,
            select = true,
        }),
        ["<C-y>"] = cmp.mapping.confirm({
            behavior = cmp.ConfirmBehavior.Replace,
            select = true,
        }),
        ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            elseif vim.fn["vsnip#available"](1) == 1 then
                feedkey("<Plug>(vsnip-expand-or-jump)", "")
            elseif has_words_before() then
                cmp.complete()
            else
                fallback() -- The fallback function sends a already mapped key. In this case, it's probably `<Tab>`.
            end
        end, { "i", "s" }),

        ["<S-Tab>"] = cmp.mapping(function()
            if cmp.visible() then
                cmp.select_prev_item()
            elseif vim.fn["vsnip#jumpable"](-1) == 1 then
                feedkey("<Plug>(vsnip-jump-prev)", "")
            end
        end, { "i", "s" }),
    },
    sources = {
        { name = "nvim_lsp" },
        { name = "buffer" },
        { name = "vsnip" },
        { name = "path" },
        { name = "emoji" },
    },
})

require("nvim-autopairs").setup({})

require("nvim-treesitter.configs").setup({
    highlight = {
        enable = true,
        disable = { "json" },
    },
    ensure_installed = "all",
    ignore_install = { "phpdoc" },
    indent = { enable = true },
    autopairs = { enable = true },
    rainbow = { enable = true },
    autotag = { enable = true },
    context_commentstring = { enable = true },
})

local function on_attach(client, bufnr)
    print("Attached to " .. client.name)
    require("lsp_signature").on_attach({
        bind = true, -- This is mandatory, otherwise border config won't get registered.
        hint_enable = false,
        handler_opts = {
            border = "single",
        },
    }, bufnr)
end

local function on_tss_attach(client, bufnr)
    on_attach(client, bufnr)
    client.server_capabilities.document_formatting = false
    client.server_capabilities.document_range_formatting = false
end

local eslint = {
    lintCommand = "eslint -f unix --stdin --stdin-filename ${INPUT}",
    lintIgnoreExitCode = false,
    lintStdin = true,
    lintFormats = { "%f:%l:%c: %m" },
    formatCommand = "eslint --fix-to-stdout --stdin --stdin-filename=${INPUT}",
    formatStdin = true,
}

local default_prettier_max_line = "100"

local prettier = {
    formatCommand = "prettier --fix-tostdout --semi --single-quote --prose-wrap always --print-width "
        .. default_prettier_max_line
        .. " --stdin-filepath ${INPUT}",
    formatStdin = true,
}

local pylint = {
    lintCommand = "pylint --output-format text --score no --msg-template {path}:{line}:{column}:{C}:{msg} ${INPUT}",
    lintStdin = false,
    lintFormats = { "%f:%l:%c:%t:%m" },
    lintOffsetColumns = 1,
    lintCategoryMap = {
        I = "H",
        R = "I",
        C = "I",
        W = "W",
        E = "E",
        F = "E",
    },
}

local black = {
    formatCommand = "black --quiet -",
    formatStdin = true,
}

local stylua = { formatCommand = "/Users/myself/.cargo/bin/stylua -s -", formatStdin = true }

local formats = {
    css = { prettier },
    html = { prettier },
    javascript = { prettier, eslint },
    javascriptreact = { prettier, eslint },
    json = { prettier },
    lua = { stylua },
    markdown = { prettier },
    scss = { prettier },
    typescript = { prettier, eslint },
    typescriptreact = { prettier, eslint },
    yaml = { prettier },
    python = { black },
}

require("lspconfig").efm.setup({
    root_dir = require("lspconfig").util.root_pattern({ ".git/", "." }),
    init_options = { documentFormatting = true, codeAction = true },
    filetypes = vim.tbl_keys(formats),
    settings = {
        rootMarkers = { ".git/", "." },
        languages = formats,
    },
})
require("lspconfig").tsserver.setup({
    on_attach = on_tss_attach,
    filetypes = {
        "javascript",
        "javascriptreact",
        "javascript.jsx",
        "typescript",
        "typescriptreact",
        "typescript.tsx",
    },
})
require("lspconfig").bashls.setup({ on_attach = on_attach })
-- require("lspconfig").graphql.setup({ on_attach = on_attach })
require("lspconfig").clangd.setup({
    on_attach = on_attach,
    root_dir = function()
        return vim.loop.cwd()
    end,
    cmd = { "clangd", "--background-index" },
})

require("lspconfig").jedi_language_server.setup({
    on_attach = on_attach,
})

require("lspconfig").yamlls.setup({})

require("lspconfig").gopls.setup({
    on_attach = on_attach,
    cmd = { "gopls", "serve" },
    settings = {
        gopls = {
            analyses = {
                unusedparams = true,
            },
            staticcheck = true,
        },
    },
})
-- who even uses this?
require("lspconfig").rust_analyzer.setup({ on_attach = on_attach })
require("lspconfig").solargraph.setup({
    root_dir = require("lspconfig").util.root_pattern(".git"), -- extra root for RN projects
})

-- require("lspconfig").flow.setup({})

require("lspconfig").sumneko_lua.setup({
    on_attach = on_attach,
    cmd = { sumneko_binary, "-E", sumneko_root_path .. "/main.lua" },
    settings = {
        Lua = {
            runtime = {
                -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
                version = "LuaJIT",
                -- Setup your lua path
                path = vim.split(package.path, ";"),
            },
            diagnostics = {
                -- Get the language server to recognize the `vim` global
                globals = { "vim" },
            },
            workspace = {
                -- Make the server aware of Neovim runtime files
                library = {
                    [vim.fn.expand("$VIMRUNTIME/lua")] = true,
                    [vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true,
                },
            },
        },
    },
})

-- git diff view
local cb = require("diffview.config").diffview_callback

require("diffview").setup({
    diff_binaries = false, -- Show diffs for binaries
    enhanced_diff_hl = false, -- See ':h diffview-config-enhanced_diff_hl'
    use_icons = true, -- Requires nvim-web-devicons
    icons = { -- Only applies when use_icons is true.
        folder_closed = "",
        folder_open = "",
    },
    signs = {
        fold_closed = "",
        fold_open = "",
    },
    file_panel = {
        winconfig = {
            position = "left", -- One of 'left', 'right', 'top', 'bottom'
            width = 35, -- Only applies when position is 'left' or 'right'
            height = 10, -- Only applies when position is 'top' or 'bottom'
        },
        listing_style = "tree", -- One of 'list' or 'tree'
        tree_options = { -- Only applies when listing_style is 'tree'
            flatten_dirs = true, -- Flatten dirs that only contain one single dir
            folder_statuses = "only_folded", -- One of 'never', 'only_folded' or 'always'.
        },
    },
    file_history_panel = {
        win_config = {
            position = "bottom",
            width = 35,
            height = 16,
        },
        log_options = {
            max_count = 256, -- Limit the number of commits
            follow = false, -- Follow renames (only for single file)
            all = false, -- Include all refs under 'refs/' including HEAD
            merges = false, -- List only merge commits
            no_merges = false, -- List no merge commits
            reverse = false, -- List commits in reverse order
        },
    },
    default_args = { -- Default args prepended to the arg-list for the listed commands
        DiffviewOpen = {},
        DiffviewFileHistory = {},
    },
    hooks = {}, -- See ':h diffview-config-hooks'
    key_bindings = {
        disable_defaults = false, -- Disable the default key bindings
        -- The `view` bindings are active in the diff buffers, only when the current
        -- tabpage is a Diffview.
        view = {
            ["<tab>"] = cb("select_next_entry"), -- Open the diff for the next file
            ["<s-tab>"] = cb("select_prev_entry"), -- Open the diff for the previous file
            ["gf"] = cb("goto_file"), -- Open the file in a new split in previous tabpage
            ["<C-w><C-f>"] = cb("goto_file_split"), -- Open the file in a new split
            ["<C-w>gf"] = cb("goto_file_tab"), -- Open the file in a new tabpage
            ["<leader>e"] = cb("focus_files"), -- Bring focus to the files panel
            ["<leader>b"] = cb("toggle_files"), -- Toggle the files panel.
        },
        file_panel = {
            ["j"] = cb("next_entry"), -- Bring the cursor to the next file entry
            ["<down>"] = cb("next_entry"),
            ["k"] = cb("prev_entry"), -- Bring the cursor to the previous file entry.
            ["<up>"] = cb("prev_entry"),
            ["<cr>"] = cb("select_entry"), -- Open the diff for the selected entry.
            ["o"] = cb("select_entry"),
            ["<2-LeftMouse>"] = cb("select_entry"),
            ["-"] = cb("toggle_stage_entry"), -- Stage / unstage the selected entry.
            ["S"] = cb("stage_all"), -- Stage all entries.
            ["U"] = cb("unstage_all"), -- Unstage all entries.
            ["X"] = cb("restore_entry"), -- Restore entry to the state on the left side.
            ["R"] = cb("refresh_files"), -- Update stats and entries in the file list.
            ["<tab>"] = cb("select_next_entry"),
            ["<s-tab>"] = cb("select_prev_entry"),
            ["gf"] = cb("goto_file"),
            ["<C-w><C-f>"] = cb("goto_file_split"),
            ["<C-w>gf"] = cb("goto_file_tab"),
            ["i"] = cb("listing_style"), -- Toggle between 'list' and 'tree' views
            ["f"] = cb("toggle_flatten_dirs"), -- Flatten empty subdirectories in tree listing style.
            ["<leader>e"] = cb("focus_files"),
            ["<leader>b"] = cb("toggle_files"),
        },
        file_history_panel = {
            ["g!"] = cb("options"), -- Open the option panel
            ["<C-A-d>"] = cb("open_in_diffview"), -- Open the entry under the cursor in a diffview
            ["y"] = cb("copy_hash"), -- Copy the commit hash of the entry under the cursor
            ["zR"] = cb("open_all_folds"),
            ["zM"] = cb("close_all_folds"),
            ["j"] = cb("next_entry"),
            ["<down>"] = cb("next_entry"),
            ["k"] = cb("prev_entry"),
            ["<up>"] = cb("prev_entry"),
            ["<cr>"] = cb("select_entry"),
            ["o"] = cb("select_entry"),
            ["<2-LeftMouse>"] = cb("select_entry"),
            ["<tab>"] = cb("select_next_entry"),
            ["<s-tab>"] = cb("select_prev_entry"),
            ["gf"] = cb("goto_file"),
            ["<C-w><C-f>"] = cb("goto_file_split"),
            ["<C-w>gf"] = cb("goto_file_tab"),
            ["<leader>e"] = cb("focus_files"),
            ["<leader>b"] = cb("toggle_files"),
        },
        option_panel = {
            ["<tab>"] = cb("select"),
            ["q"] = cb("close"),
        },
    },
})
" Pythons and Perls
let g:python_host_prog = '/home/myself/.pyenv/versions/py2nvim/bin/python2' 
let g:python3_host_prog = '/home/myself/.pyenv/versions/py3nvim/bin/python3' 
let g:loaded_perl_provider = 0

" Plugins
call plug#begin('~/.vim/plugged')

" Completion and LSP features
Plug 'neovim/nvim-lspconfig'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/cmp-emoji',
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-vsnip'
Plug 'hrsh7th/vim-vsnip'
Plug 'ray-x/lsp_signature.nvim'
Plug 'windwp/nvim-ts-autotag'

" Formatting & Linting
Plug 'sbdchd/neoformat'
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}

" Snippets and shortcuts
Plug 'windwp/nvim-autopairs'
Plug 'rafamadriz/friendly-snippets'
Plug 'tpope/vim-commentary'
Plug 'github/copilot.vim'

" Navigation
Plug 'preservim/nerdtree'
Plug 'mbbill/undotree'
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-telescope/telescope.nvim'

" Git
Plug 'tpope/vim-fugitive'
Plug 'APZelos/blamer.nvim'
Plug 'sindrets/diffview.nvim'

" Visuals
Plug 'gruvbox-community/gruvbox'
Plug 'nathanaelkane/vim-indent-guides'
Plug 'vim-airline/vim-airline'
Plug 'tpope/vim-markdown'
Plug 'rafi/awesome-vim-colorschemes'
Plug 'dracula/vim', { 'as': 'dracula' }
call plug#end()

" Load lua configs
lua require('myself')

" Set nohlsearch
set nohlsearch

" Copy / Paste
vnoremap <C-c> "+y
nmap <C-v> "+p

" Mouse
set mouse=nv

" Color
colo gruvbox
set termguicolors
let g:gruvbox_contrast_dark = 'hard'
set background=dark
hi Normal guifg=#ded8c8 guibg=#1c1b1b
hi GruvboxPurple guifg=#987699
hi ColorColumn guibg=#212121

" Relative number
set number relativenumber nuw=1

" Ignorecase / smartcase
set ignorecase smartcase

" Autocompletion (shell)
set wildmode=longest,list,full
set wildmenu
" Ignore files
set wildignore+=*.pyc
set wildignore+=*_build/*
set wildignore+=**/coverage/*
set wildignore+=**/node_modules/*
set wildignore+=**/android/*
set wildignore+=**/ios/*
set wildignore+=**/.git/*

" Split window opens below and to the right (not the opposite)
set splitbelow splitright

" Airline to use powerline fonts 
let g:airline_powerline_fonts = 1

" Leader key
let mapleader = " "

" Spell check
nmap <leader>o :setlocal spell!<CR>

" NerdTREE
map <silent><C-n> :NERDTreeToggle<CR>
map <silent><leader><C-n> :NERDTreeFind<CR>
let NERDTreeShowHidden=1
let NERDTreeQuitOnOpen=1

" UndoTREE
nnoremap <leader>u :UndotreeToggle<CR>

function! WindowLeft()
    if (&buftype != "nofile")
      execute "normal! :set wfw!\<CR>"
      execute "normal! \<C-w>h"
      if (&buftype != "nofile")
        execute "normal! :vertical resize 126\<CR>:set wfw\<CR>\<C-w>=0"
      endif
    else
      execute "normal! :set wfw\<CR>"
    endif
endfunction

" This is my old window management (inside vim). I actually sometimes use it
" still.
function! WindowRight()
    if (&buftype != "nofile")
      execute "normal! :set wfw!\<CR>"
      execute "normal! \<C-w>l"
      if (&buftype != "nofile")
        execute "normal! :vertical resize 126\<CR>:set wfw\<CR>\<C-w>=0"
      endif
    else
      execute "normal! :set wfw\<CR>"
      execute "normal! \<C-w>l"
      if (&buftype != "nofile")
        execute "normal! :NERDTreeToggle\<CR>"
      endif
    endif
endfunction

" Window Navigation
tnoremap <silent><C-j> <C-w>N:resize 16<CR>a
tnoremap <silent><C-k> <C-w>N:resize 3<CR>a<C-w>k
tnoremap <silent><C-h> <C-w>N:resize 3<CR>a<C-w>k<C-w>h
tnoremap <silent><C-l> <C-w>N:resize 3<CR>a<C-w>k<C-w>l
nnoremap <C-h> :call WindowLeft()<CR>
nnoremap <C-l> :call WindowRight()<CR>
nnoremap <silent><C-j> <C-W>j
nnoremap <silent><C-k> <C-W>k
nnoremap <leader><C-o> <C-w>x
nnoremap <leader><C-l> gt
nnoremap <leader><C-h> gT
nnoremap ≥ <C-W>>
nnoremap ≤ <C-W><lt>
" nnoremap <M-,> <C-W>-
" nnoremap <M-.> <C-w>+

" git blamer
nmap <leader>gb :BlamerToggle<CR>
let g:blamer_template = '<author>, <committer-time> • <summary>'

" commenting
inoremap /**<CR> /**<CR> *<CR> */<Esc>kA 
xmap <C-_> <Plug>Commentary
nmap <C-_> <Plug>Commentary
omap <C-_> <Plug>Commentary
nmap <C-_> <Plug>CommentaryLine

" wrapping text with
vnoremap <leader>{ di{}<ESC>hp
vnoremap <leader>` di``<ESC>hp
vnoremap <leader>[ di[]<ESC>hp
vnoremap <leader>( di()<ESC>hp
vnoremap <leader>" di""<ESC>hp
vnoremap <leader>' di''<ESC>hp
vnoremap <leader>~ di~~<ESC>hp
vnoremap <leader>/* di/*<CR>*/<ESC>kp

" e-regex searches
:nnoremap / /\v
:cnoremap s/ s/\v

" no errorbells
set noerrorbells

" backup swap undo
set backupdir=~/.vim-dirs/backup//
set directory=~/.vim-dirs/swap//
set undodir=~/.vim-dirs/undo//

" no wrap / colorcolumn
set nowrap
set colorcolumn=120
nnoremap <leader>in :IndentGuidesToggle<CR>

" Reading Podfiles as Ruby files
autocmd BufNewFile,BufRead Podfile set filetype=ruby
autocmd BufNewFile,BufRead *.podspec set filetype=ruby

" Close quickfix after selecting item
" autocmd FileType qf nnoremap <buffer> <CR> <CR>:cclose<CR>

" Automatically restore to last read line
autocmd BufReadPost *
      \ if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit'
      \ |   exe "normal! g`\""
      \ | endif

" fixing tab
set tabstop=2 softtabstop=0 expandtab shiftwidth=2 smarttab

" Disable auto-commenting new lines
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o

" hide buffers instead of closing them
set hidden

" Debugging syntax highlighting
nnoremap <leader>f1 :echo synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>
nnoremap <leader>f2 :echo ("hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">")<cr>
nnoremap <leader>f3 :echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')<cr>
nnoremap <leader>f4 :exec 'syn list '.synIDattr(synID(line('.'), col('.'), 0), 'name')<cr>

" matchit
packadd! matchit

" copilot
imap <silent><script><expr> <C-J> copilot#Accept("\<C-N>")
let g:copilot_no_tab_map = v:true

" alternative auto change dir (autochdir)
" set autochdir
nnoremap <leader>cd :cd %:h<CR>:pwd<CR>

" markdown syntax highlighting
au BufNewFile,BufRead *.md set filetype=markdown
let g:markdown_fenced_languages = ['html', 'python', 'bash=sh', 'ts=typescript', 'typescript', 'js=javascript', 'javascript']

" Jump forward or backward
imap <expr> <Tab>   vsnip#jumpable(1)   ? '<Plug>(vsnip-jump-next)'      : '<Tab>'
smap <expr> <Tab>   vsnip#jumpable(1)   ? '<Plug>(vsnip-jump-next)'      : '<Tab>'
imap <expr> <S-Tab> vsnip#jumpable(-1)  ? '<Plug>(vsnip-jump-prev)'      : '<S-Tab>'
smap <expr> <S-Tab> vsnip#jumpable(-1)  ? '<Plug>(vsnip-jump-prev)'      : '<S-Tab>'

" Load helps
packloadall
silent! helptags ALL
filetype plugin indent on
JoosepAlviste commented 2 years ago

Ahhh I see what could be the problem. The vim-commentary integration of this plugin is kind of hacky and only works with the default mappings. Since you have customized the mappings, then it won't work for you out of the box.

Could you try updating your commentary mappings to follow the configuration in this plugin? https://github.com/JoosepAlviste/nvim-ts-context-commentstring/blob/main/lua/ts_context_commentstring/integrations/vim_commentary.lua

Basically, wrapping the mappings in v:lua.context_commentstring.update_commentstring_and_run. Something like this should work (I haven't written a vimscript mapping in a while, so the syntax might not be 100% correct 😄):

nmap <expr> <C-_> v:lua.context_commentstring.update_commentstring_and_run('Commentary')
andrestone commented 2 years ago

Yep, it worked.

Thanks for helping!