1
0
mirror of https://github.com/a-h/templ.git synced 2025-02-06 09:45:21 +00:00

feat: add Nix development flake with Neovim config

This commit is contained in:
Adrian Hesketh 2023-04-23 17:42:57 +01:00
parent a6d664d014
commit 3c0c2b7867
No known key found for this signature in database
GPG Key ID: 9E01387222323123
21 changed files with 683 additions and 7 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
.git
Dockerfile
.dockerignore

11
Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM nixos/nix
RUN nix-channel --update
COPY ./nix/nix.conf /etc/nix/nix.conf
RUN mkdir /templ
COPY . /templ
WORKDIR /templ
RUN nix develop --impure --command printf "Build complete\n"
COPY ./nix/.config /root/.config
# Open port for templ LSP HTTP debugging
EXPOSE 7474
CMD nix develop --impure

View File

@ -645,6 +645,14 @@ To add extensive debug information, you can include additional args to the LSP,
## Tasks
### nix-develop
Run a Nix shell that contains everything required to build templ.
```sh
nix develop --impure
```
### build
Build a local version.
@ -743,6 +751,22 @@ Directory: docs
npm run build
```
### docker-build
Build a Docker container with a full development environment and Neovim setup for testing the LSP.
```
docker build -t templ:latest .
```
### docker-run
Run a Docker development container in the current directory.
```
docker run -p 7474:7474 -v `pwd`:/templ -it --rm templ:latest
```
# Code signing
The binaries are created by me and signed by my GPG key. You can verify with my key https://adrianhesketh.com/a-h.gpg

View File

@ -146,6 +146,10 @@ func (d *Document) String() string {
return strings.Join(d.Lines, "\n")
}
func (d *Document) Replace(with string) {
d.Lines = strings.Split(with, "\n")
}
func (d *Document) Apply(r *lsp.Range, with string) {
withLines := strings.Split(with, "\n")
d.normalize(r)

View File

@ -631,6 +631,7 @@ func (p *Server) Formatting(ctx context.Context, params *lsp.DocumentFormattingP
},
NewText: w.String(),
})
d.Replace(w.String())
return
}

View File

@ -0,0 +1,25 @@
---
sidebar_position: 4
---
# For loops
templ supports iterating over slices, arrays and channels etc. using the for loop:
```templ
templ listNames(items []Item) {
<ul>
for _, item := range items {
<li>{ item.Name }</li>
}
</ul>
}
```
```html
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
```

View File

@ -1,7 +0,0 @@
---
sidebar_position: 4
---
# Loops
`todo`

225
flake.lock generated Normal file
View File

@ -0,0 +1,225 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"go": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1682161870,
"narHash": "sha256-totoTsRI/ISHixAJgvx26291cyXGVRyG9gRf4ZnppKw=",
"owner": "a-h",
"repo": "nix-golang",
"rev": "239c45506fa0f6d78b4842760acd316f6b473069",
"type": "github"
},
"original": {
"owner": "a-h",
"repo": "nix-golang",
"type": "github"
}
},
"neovim-flake": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs"
},
"locked": {
"dir": "contrib",
"lastModified": 1680866789,
"narHash": "sha256-4uCPWnjSMU7ac6Q3LT+Em8lVk1MuSegxHMLGQRtFqAs=",
"owner": "neovim",
"repo": "neovim",
"rev": "040f1459849ab05b04f6bb1e77b3def16b4c2f2b",
"type": "github"
},
"original": {
"dir": "contrib",
"owner": "neovim",
"repo": "neovim",
"type": "github"
}
},
"neovim-nightly-overlay": {
"inputs": {
"flake-compat": "flake-compat",
"neovim-flake": "neovim-flake",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1682237548,
"narHash": "sha256-7bXfvT8S2O+aqIfLsDk7eTQjX4JrchHh7TyqGCA5zPI=",
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"rev": "3594ebd0f70ebc4553bb9e16accb1fd868dc3125",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1681920287,
"narHash": "sha256-+/d6XQQfhhXVfqfLROJoqj3TuG38CAeoT6jO1g9r1k0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "645bc49f34fa8eff95479f0345ff57e55b53437e",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1681932375,
"narHash": "sha256-tSXbYmpnKSSWpzOrs27ie8X3I0yqKA6AuCzCYNtwbCU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3d302c67ab8647327dba84fbdb443cdbf0e82744",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.11",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"go": "go",
"neovim-nightly-overlay": "neovim-nightly-overlay",
"nixpkgs": "nixpkgs_2",
"xc": "xc"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"xc": {
"inputs": {
"flake-utils": "flake-utils_4",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1681392057,
"narHash": "sha256-jBOf1n6NfA9S9NjD3moMNiRBs1/I0lEMqTsflha/QuE=",
"owner": "joerdav",
"repo": "xc",
"rev": "feb8b4fad05f5139ba997af4aafa0ff44efb31ad",
"type": "github"
},
"original": {
"owner": "joerdav",
"repo": "xc",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

66
flake.nix Normal file
View File

@ -0,0 +1,66 @@
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "nixpkgs/nixos-22.11";
xc = {
url = "github:joerdav/xc";
inputs.nixpkgs.follows = "nixpkgs";
};
go = {
url = "github:a-h/nix-golang";
inputs.nixpkgs.follows = "nixpkgs";
};
neovim-nightly-overlay = {
url = "github:nix-community/neovim-nightly-overlay";
inputs.nixpkgs.follows = "nixpkgs";
# Neovim 0.9.0
inputs.neovim-flake.url = "github:neovim/neovim?dir=contrib&rev=040f1459849ab05b04f6bb1e77b3def16b4c2f2b";
};
};
outputs = { self, flake-utils, nixpkgs, xc, go, neovim-nightly-overlay }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgsDefault = import nixpkgs { overlays = [ neovim-nightly-overlay.overlay ]; };
pkgs = import nixpkgs {
inherit system; overlays = [
(self: super: {
xc = xc.packages.${system}.xc;
neovim = import ./nix/nvim.nix { pkgs = pkgsDefault; };
go = go.packages.${system}.go_1_20_3;
gopls = pkgs.callPackage ./nix/gopls.nix { };
templ = pkgs.callPackage ./nix/templ.nix {
go = self.go;
xc = self.xc;
};
nerdfonts = (pkgsDefault.nerdfonts.override { fonts = [ "IBMPlexMono" ]; });
})
];
};
shell = pkgs.mkShell {
packages = [
pkgs.asciinema
pkgs.git
pkgs.go
pkgs.gopls
pkgs.gotools
pkgs.ibm-plex
pkgs.neovim
pkgs.nerdfonts
pkgs.ripgrep
pkgs.silver-searcher
pkgs.templ
pkgs.tmux
pkgs.wget
pkgs.xc
pkgs.zip
];
};
in
{
devShells = {
default = shell;
};
}
);
}

View File

@ -0,0 +1,9 @@
-- Autoformat Go files on save and add goimports style fix-up.
-- See https://github.com/neovim/nvim-lspconfig/issues/115
vim.api.nvim_create_autocmd('BufWritePre', {
pattern = '*.go',
callback = function()
vim.lsp.buf.code_action({ context = { only = { 'source.organizeImports' } }, apply = true })
end
})

View File

@ -0,0 +1,5 @@
require('goimports')
require('lsp')
require('settings')
require('theme')
require('treesitter')

View File

@ -0,0 +1,158 @@
local nvim_lsp = require('lspconfig')
-- https://github.com/ray-x/lsp_signature.nvim
local lsp_signature_cfg = {
hint_prefix = '',
handler_opts = {
border = "none"
},
padding = ' '
}
require 'lsp_signature'.setup(lsp_signature_cfg) -- no need to specify bufnr if you don't use toggle_key
-- Format on save.
vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]]
-- Mappings.
local opts = { noremap = true, silent = true }
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
--Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.format { async = true }<CR>', opts)
buf_set_keymap('n', '<space>clr', '<cmd>lua vim.lsp.codelens.refresh()<CR>', opts)
buf_set_keymap('n', '<space>cln', '<cmd>lua vim.lsp.codelens.run()<CR>', opts)
-- TypeScript organise imports.
buf_set_keymap('n', '<space>tsoi',
'<cmd>lua vim.lsp.buf.execute_command({command = "_typescript.organizeImports", arguments = {vim.fn.expand("%:p")}})<CR>'
, opts)
buf_set_keymap('n', '<space>tsf', '<cmd>EslintFixAll<CR>', opts)
end
-- Add templ configuration.
local configs = require('lspconfig.configs')
configs.templ = {
default_config = {
cmd = { "templ", "lsp", "-http=localhost:7474", "-log=/templ-lsp.log" },
filetypes = { 'templ' },
root_dir = nvim_lsp.util.root_pattern("go.mod", ".git"),
settings = {},
};
}
-- Add additional capabilities supported by nvim-cmp
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
local server_settings = {
gopls = {
gopls = {
codelenses = {
generate = true, -- show the `go generate` lens.
gc_details = true, -- show a code lens toggling the display of gc's choices.
test = true,
upgrade_dependency = true,
tidy = true,
},
},
},
tsserver = {
format = { enable = false },
},
eslint = {
enable = true,
format = { enable = true }, -- this will enable formatting
packageManager = "npm",
autoFixOnSave = true,
codeActionOnSave = {
mode = "all",
rules = { "!debugger", "!no-only-tests/*" },
},
lintTask = {
enable = true,
},
},
}
-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
-- eslint comes from:
-- npm i -g vscode-langservers-extracted
local servers = { 'gopls', 'tsserver', 'templ', 'eslint' }
for _, lsp in ipairs(servers) do
local lsp_opts = {
on_attach = on_attach,
capabilities = capabilities,
}
if server_settings[lsp] then lsp_opts.settings = server_settings[lsp] end
nvim_lsp[lsp].setup(lsp_opts)
end
--vim.lsp.set_log_level("debug")
-- Use :LspLog to see logs.
-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menuone,noselect'
-- nvim-cmp setup
local cmp = require 'cmp'
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
end,
},
window = {
-- completion = cmp.config.window.bordered(),
-- documentation = cmp.config.window.bordered(),
},
mapping = cmp.mapping.preset.insert({
['<C-b>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.abort(),
['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'vsnip' },
}, {
{ name = 'buffer' },
})
})
-- https://github.com/samhh/dotfiles/blob/ba63ff91a33419dfb08e412a7d832b2aca38148c/home/.config/nvim/plugins.vim#L151
vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
vim.lsp.diagnostic.on_publish_diagnostics,
{
virtual_text = false,
signs = true,
update_in_insert = false,
underline = true,
}
)

View File

@ -0,0 +1,22 @@
vim.opt.autoindent = true
vim.opt.encoding = "utf-8"
vim.opt.fileencoding = "utf-8"
vim.opt.tabstop = 2
-- Set termguicolors to enable highlight groups.
vim.opt.termguicolors = true
-- Move the preview screen.
vim.opt.splitbelow = true
-- Make it so that the gutter (left column) doesn't move.
vim.opt.signcolumn = "yes"
-- Set line numbers to be visible all of the time.
vim.opt.number = true
-- Disable mouse control.
vim.cmd("set mouse=")
-- Use system clipboard.
--vim.api.nvim_command('set clipboard+=unnamedplus')

View File

@ -0,0 +1,24 @@
-- Set colors.
-- To find available colours to set, use `:hi <name>` to search through
-- available colours.
local dracula = require("dracula")
dracula.setup({
-- set custom lualine background color
lualine_bg_color = "#44475a", -- default nil
transparent_bg = true,
-- overrides the default highlights see `:h synIDattr`
overrides = {
-- Examples
-- NonText = { fg = dracula.colors().white }, -- set NonText fg to white
-- NvimTreeIndentMarker = { link = "NonText" }, -- link to NonText highlight
-- Nothing = {} -- clear highlight of Nothing
['@type.builtin'] = {
fg = dracula.colors().cyan,
italic = false,
},
},
})
vim.cmd [[colorscheme dracula]]
-- Floating window.
vim.cmd [[hi Pmenu guibg=NONE]]

View File

@ -0,0 +1,5 @@
require('nvim-treesitter.configs').setup {
highlight = {
enable = true,
},
}

22
nix/gopls.nix Normal file
View File

@ -0,0 +1,22 @@
{ lib, buildGoModule, fetchFromGitHub }:
buildGoModule rec {
pname = "gopls";
version = "0.10.1";
src = fetchFromGitHub {
owner = "golang";
repo = "tools";
rev = "8321f7bbcfd30300762661ed9188226b42e27ec1";
sha256 = "9WDqd8Xgiov/OFAFl5yZmon4o3grbOxzZs3wnNu7pbg=";
};
vendorSha256 = "EZ/XPta2vQfemywoC2kbTamJ43K4tr4I7mwVzrTbRkA=";
modRoot = "gopls";
subPackages = [ "." ];
meta = with lib; {
platforms = platforms.linux ++ platforms.darwin;
};
}

4
nix/nix.conf Normal file
View File

@ -0,0 +1,4 @@
experimental-features = nix-command flakes
build-users-group = nixbld
sandbox = false
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=

52
nix/nvim.nix Normal file
View File

@ -0,0 +1,52 @@
{ pkgs, ... }:
let
pluginGit = owner: repo: ref: sha: pkgs.vimUtils.buildVimPluginFrom2Nix {
pname = "${repo}";
version = ref;
src = pkgs.fetchFromGitHub {
owner = owner;
repo = repo;
rev = ref;
sha256 = sha;
};
};
# See list of grammars.
# https://github.com/NixOS/nixpkgs/blob/c4fcf9a2cc4abde8a2525691962b2df6e7327bd3/pkgs/applications/editors/vim/plugins/nvim-treesitter/generated.nix
nvim-treesitter-with-plugins = pkgs.vimPlugins.nvim-treesitter.withPlugins (p: [
p.go
p.gomod
p.javascript
p.json
p.nix
p.html
p.tsx
p.typescript
p.yaml
p.dockerfile
]);
in
pkgs.neovim.override {
vimAlias = true;
configure = {
packages.myPlugins = with pkgs.vimPlugins; {
start = [
(pluginGit "Mofiqul" "dracula.nvim" "a0b129d7dea51b317fa8064f13b29f68004839c4" "snCRLw/QtKPDAkh1CXZfto2iCoyaQIx++kOEC0vy9GA=")
# Tressiter syntax highlighting.
nvim-treesitter-with-plugins
# Templ highlighting.
(pluginGit "Joe-Davidson1802" "templ.vim" "2d1ca014c360a46aade54fc9b94f065f1deb501a" "1bc3p0i3jsv7cbhrsxffnmf9j3zxzg6gz694bzb5d3jir2fysn4h")
# Configure autocomplete.
(pluginGit "neovim" "nvim-lspconfig" "cf95480e876ef7699bf08a1d02aa0ae3f4d5f353" "mvDg+aT5lldqckQFpbiBsXjnwozzjKf+v3yBEyvcVLo=")
# Add function signatures to autocomplete.
(pluginGit "ray-x" "lsp_signature.nvim" "1fdc742af68f4725a22c05c132f971143be447fc" "DITo8Sp/mcOPhCTcstmpb1i+mUc5Ao8PEP5KYBO8Xdg=")
# Configure autocomplete.
(pluginGit "hrsh7th" "nvim-cmp" "777450fd0ae289463a14481673e26246b5e38bf2" "CoHGIiZrhRAHZ/Er0JSQMapI7jwllNF5OysLlx2QEik=")
(pluginGit "hrsh7th" "vim-vsnip" "7753ba9c10429c29d25abfd11b4c60b76718c438" "ehPnvGle7YrECn76YlSY/2V7Zeq56JGlmZPlwgz2FdE=")
(pluginGit "hrsh7th" "cmp-nvim-lsp" "0e6b2ed705ddcff9738ec4ea838141654f12eeef" "DxpcPTBlvVP88PDoTheLV2fC76EXDqS2UpM5mAfj/D4=")
];
opt = [ ];
};
customRC = "lua require('init')";
};
}

1
nix/run.sh Executable file
View File

@ -0,0 +1 @@
docker run -v `pwd`/nix.conf:/etc/nix/nix.conf -v `pwd`:/conf -it --rm templ-neovim

11
nix/templ-install.sh Executable file
View File

@ -0,0 +1,11 @@
# Create the standard environment.
source $stdenv/setup
# Go requires a cache directory so let's point it at one.
mkdir -p /tmp/go-cache
export GOCACHE=$TMPDIR/go-cache
export GOMODCACHE=$TMPDIR/go-cache
# Build the source code.
cd $src/cmd/templ
# Build the templ binary and output it.
mkdir -p $out/bin
go build -o $out/bin/templ

11
nix/templ.nix Normal file
View File

@ -0,0 +1,11 @@
{ pkgs, stdenv, go, xc }:
stdenv.mkDerivation {
pname = "templ";
version = "devel";
src = ./..;
builder = ./templ-install.sh;
system = builtins.currentSystem;
nativeBuildInputs = [ go xc ];
}