return {
	{
		"nvim-treesitter/nvim-treesitter",
		event = { "BufReadPre", "BufNewFile" },
		build = ":TSUpdate",
		dependencies = {
			"windwp/nvim-ts-autotag",
            "nvim-treesitter/nvim-treesitter-textobjects",
		},
		config = function()
			-- import nvim-treesitter plugin
			local treesitter = require("nvim-treesitter.configs")

			-- configure treesitter
			treesitter.setup({
                -- enable syntax highlighting
				highlight = {
					enable = true,
				},
				-- enable indentation
				indent = { enable = true },
				-- enable autotagging (w/ nvim-ts-autotag plugin)
				autotag = { enable = true },
				-- ensure these language parsers are installed
				ensure_installed = {
					"json",
					"javascript",
					"typescript",
					"tsx",
					"yaml",
					"html",
					"css",
					"prisma",
					"markdown",
					"markdown_inline",
					"svelte",
					"graphql",
					"bash",
					"lua",
					"vim",
					"dockerfile",
					"gitignore",
					"php",
				},
				-- enable nvim-ts-context-commentstring plugin for commenting tsx and jsx
				context_commentstring = {
					enable = true,
					enable_autocmd = false,
				},
				-- auto install above language parsers
				auto_install = true,

                textobjects = {
                    select = {
                        enable = true,

                        -- Automatically jump forward to textobj, similar to targets.vim
                        lookahead = true,

                        keymaps = {
                            -- You can use the capture groups defined in textobjects.scm
                            ["aa"] = "@parameter.outer",
                            ["ia"] = "@parameter.inner",

                            ["af"] = "@function.outer",
                            ["if"] = "@function.inner",

                            ["ac"] = "@class.outer",
                            ["ic"] = "@class.inner",

                            ["ab"] = "@block.outer",
                            ["ib"] = "@block.inner",

                            ["al"] = "@loop.outer",
                            ["il"] = "@loop.inner",

                            ["am"] = "@call.outer",
                            ["im"] = "@call.inner",

                            ["ai"] = "@conditional.outer",
                            ["ii"] = "@conditional.inner",
                        },
                        selection_modes = {
                            ['@parameter.outer'] = 'v', -- charwise
                            ['@function.outer'] = 'V', -- linewise
                            ['@class.outer'] = '<c-v>', -- blockwise
                        },
                        include_surrounding_whitespace = true,
                    },
                    move = {
                        enable = true,
                        set_jumps = true, -- whether to set jumps in the jumplist
                        goto_next_start = {
                            ["]m"] = "@function.outer",
                            ["]]"] = "@class.outer",
                        },
                        goto_next_end = {
                            ["]M"] = "@function.outer",
                            ["]["] = "@class.outer",
                        },
                        goto_previous_start = {
                            ["[m"] = "@function.outer",
                            ["[["] = "@class.outer",
                        },
                        goto_previous_end = {
                            ["[M"] = "@function.outer",
                            ["[]"] = "@class.outer",
                        },
                        goto_next = {
                            ["]i"] = "@conditional.outer",
                            ["]l"] = "@loop.outer",
                        },
                        goto_previous = {
                            ["[i"] = "@conditional.outer",
                            ["[l"] = "@loop.outer",
                        }
                    },
                    swap = {
                        enable = true,
                        swap_next = {
                            ["<leader>s"] = "@parameter.inner",
                        },
                        swap_previous = {
                            ["<leader>S"] = "@parameter.inner",
                        },
                    },
                },
            })

            local ts_repeat_move = require("nvim-treesitter.textobjects.repeatable_move")

            local keymap = vim.keymap

            -- vim way: ; goes to the direction you were moving.
            keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move)
            keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_opposite)

            -- Optionally, make builtin f, F, t, T also repeatable with ; and ,
            keymap.set({ "n", "x", "o" }, "f", ts_repeat_move.builtin_f)
            keymap.set({ "n", "x", "o" }, "F", ts_repeat_move.builtin_F)
            keymap.set({ "n", "x", "o" }, "t", ts_repeat_move.builtin_t)
            keymap.set({ "n", "x", "o" }, "T", ts_repeat_move.builtin_T)
        end,
    },
}
