Compare commits

109 Commits
Author SHA1 Message Date
chris 603e7a2b7a Add autocommand to update shortcuts files 2026-07-21 21:09:03 +01:00
Chris ae26197a78 Update 2026-07-14 11:54:55 +01:00
Chris 29f4436aa8 Better projects 2026-07-11 13:16:12 +01:00
Chris f9f6aea868 Fix blade nav 2026-07-09 17:33:16 +01:00
Chris ffc4520ba9 More projects 2026-07-09 17:27:30 +01:00
Chris bf0b652992 Update files 2026-07-09 16:43:59 +01:00
Chris 6e5fc4d1b4 Merge branch 'main' of labs.scarif.space:chris/nvim 2026-07-08 08:58:49 +01:00
Chris 64723103b6 Update files 2026-07-08 08:58:18 +01:00
chris a2d915bbd1 Update files 2026-07-04 21:47:12 +01:00
chris 4fbd8fce83 Remove conform 2026-07-04 20:36:19 +01:00
Chris 7198cb031a Update files 2026-07-03 16:05:57 +01:00
Chris fbcdd3af0c Formatting 2026-07-03 13:48:02 +01:00
chris 12b0d3d8b8 Remove blade-nav 2026-06-18 21:50:07 +01:00
Chris 9c6d49cd5d Always render markdown 2026-06-17 07:48:33 +01:00
chris fff9a0e70e Update files 2026-06-16 22:03:42 +01:00
Chris ecbc266165 Cheatsheets and debuggin 2026-06-16 16:26:28 +01:00
Chris 5dd9b59b90 Force saving 2026-05-14 16:30:06 +01:00
Chris 1768a69cf1 Blade 2026-05-06 09:30:50 +01:00
Chris 35e45b9fd5 Update files 2026-05-04 13:43:47 +01:00
chris 086682194b Refactor causing issues 2026-04-28 21:33:20 +01:00
Chris 96ddb7a611 Stuff 2026-04-21 08:00:23 +01:00
Chris bd2349c1ba Merge branch 'main' of labs.scarif.space:chris/nvim 2026-03-31 14:15:49 +01:00
Chris b4fd6c1988 Fixing treesitter 2026-03-31 14:15:12 +01:00
chris 8d1278b84a Fix pywal missing 2026-03-09 23:20:40 +00:00
chris e4a935de25 Use tokyo for fallback 2026-03-08 20:58:50 +00:00
chris d8732c5e2e Update files 2026-03-08 20:50:10 +00:00
chris ba41c9a054 Add pywal theme 2026-03-08 20:48:24 +00:00
chris 894d2fcabf Update files 2026-03-06 17:06:16 +00:00
chris 40adefb70c Update files 2026-03-06 17:05:20 +00:00
chris faea500177 Update files 2026-03-06 17:02:36 +00:00
chris 6f74961fc6 Fix treesitter 2026-03-01 20:52:19 +00:00
chris cc7139c2ff Add keymap to reload file 2026-02-22 20:02:46 +00:00
Chris bac22a5657 Comment out annoying snippets 2026-02-19 09:04:46 +00:00
chris 20d080e223 Stuff 2026-02-15 21:35:09 +00:00
chris 847c71a194 Update projects 2025-12-23 22:52:37 +00:00
Chris 78b8bf177c Merge branch 'main' of labs.scarif.space:chris/nvim 2025-12-18 09:18:41 +00:00
Chris 4f8e722f13 Snippets 2025-12-18 09:18:00 +00:00
chris 1f58b9f136 More snippets 2025-12-17 16:52:51 +00:00
Chris 4d3aada204 Remove textobjects 2025-12-10 14:26:27 +00:00
Chris d53821dbf7 textobjects 2025-12-10 11:47:00 +00:00
chris e89dbcac87 Cool stuff 2025-12-09 23:07:24 +00:00
chris 5bf1ec232e Super keymaps 2025-12-09 22:49:24 +00:00
chris aded597ffe Trying stuff 2025-12-09 22:10:16 +00:00
Chris 282301e206 Plugins 2025-12-09 16:24:08 +00:00
chris 9bd219f053 Snippets 2025-12-09 10:35:51 +00:00
chris 0cce7837f2 God of snippets 2025-12-08 20:18:20 +00:00
Chris f79e89d335 Snippets 2025-12-08 16:33:11 +00:00
Chris 1f5a3d19f2 Migrate map 2025-12-08 09:29:10 +00:00
chris dc5d2e20ff Snippets 2025-12-08 00:52:01 +00:00
chris 256a5695ed Super keymaps 2025-12-07 18:47:34 +00:00
chris 2a4578e1eb Better typescript 2025-11-21 19:36:05 +00:00
chris 52ae098ac6 Add laravel maps 2025-11-16 10:01:02 +00:00
chris 1c96d03649 Fix some things 2025-11-15 13:55:47 +00:00
Chris 344623eaf6 Hylark settings 2025-11-12 09:21:24 +00:00
chris f16cb91875 Stuff 2025-11-11 22:58:02 +00:00
chris 8e2d413e0a Yazi plugin 2025-11-11 21:51:41 +00:00
chris 2062c442b2 Fix copilot check 2025-11-10 20:58:07 +00:00
Chris 2255489fd8 Sharing config 2025-11-10 09:19:30 +00:00
chris a21a1a3386 More changes 2025-11-09 23:03:51 +00:00
chris 529cfa79c8 More project specific stuff 2025-11-07 22:10:53 +00:00
chris f8f6d8e776 Quicker and project specific settings 2025-11-07 14:27:25 +00:00
chris 5016dd4ee8 Add completion ignore ft 2025-10-29 20:29:38 +00:00
chris 37b4d8a6e4 Ignore buffer 2025-10-25 14:50:02 +01:00
Chris d44eac696f Remove 2025-10-21 09:52:22 +01:00
Chris 5c08ce032e Rename files 2025-10-21 09:50:49 +01:00
chris 9415b1df07 More on AI 2025-10-19 13:07:29 +01:00
chris 406e5cfe8e AI stuff 2025-10-19 10:01:51 +01:00
Chris 6a0c90bf26 Merge branch 'main' of labs.scarif.space:chris/nvim 2025-09-08 09:22:01 +01:00
Chris 7744e83086 Update snippets 2025-09-08 09:20:42 +01:00
chris d4ecc5aa67 Improve debugging 2025-09-08 09:19:08 +01:00
Chris 2b1d2ed5be Update snippets 2025-08-26 18:23:17 +01:00
chris ca6e7089fa Type 2025-08-23 12:16:33 +01:00
chris 4f6f50cd6f Update phpactor 2025-08-13 09:04:55 +01:00
Chris b4821e8a52 Import with extensions 2025-07-30 16:20:50 +01:00
Chris dc0fed3735 Cleaning up 2025-07-25 12:32:22 +01:00
Chris b72760d868 Remove go server 2025-07-24 14:34:27 +01:00
Chris 7ec52ae64a Merge branch 'main' of labs.scarif.space:chris/nvim 2025-07-24 14:31:25 +01:00
Chris 278f31d4ea Fixing lsp 2025-07-24 14:27:38 +01:00
chris ebb69274ba Update aider and projects 2025-07-19 11:52:57 +01:00
chris ff00984c4e Reordering 2025-07-01 22:44:17 +01:00
chris 6fb67640ef Improve dashboard 2025-07-01 22:39:59 +01:00
Chris 2dc48b5b4c More aider commands 2025-06-30 09:10:05 +01:00
chris 379f2acd55 Update aider shortcut 2025-06-26 16:46:04 +01:00
chris ed1f52af11 Comment out vectorcode 2025-06-20 22:16:56 +01:00
Chris f090b1a43e More settings 2025-05-12 17:09:14 +01:00
Chris 4975f4c459 Improvements to Code companion 2025-05-12 09:04:50 +01:00
Chris d97fdc798f Lighten line number colors 2025-05-12 09:04:50 +01:00
chris 6f3a5a40e5 Install Aider 2025-05-11 18:22:49 +01:00
Chris ea9ee8267a Start on insert mode 2025-05-08 07:59:46 +01:00
Chris b8d7a1c9ab Updating debug 2025-05-07 07:58:00 +01:00
Chris ed622165b8 Fixing some things 2025-05-06 07:18:21 +01:00
chris 3ba111e55c Fix typo 2025-05-05 07:28:57 +01:00
chris c084f286a1 Merge branch 'fix-detached' 2025-05-05 07:28:04 +01:00
chris acccc74130 Fixing the keymap for changing model 2025-05-05 07:27:24 +01:00
chris c329bab9d6 Adding MCP Hub 2025-05-05 07:25:00 +01:00
Chris 6dfef7bd87 Upgrade config 2025-05-02 20:58:31 +01:00
Chris 17e642dcd3 Adding some snippets and keymaps 2025-04-29 17:22:36 +01:00
chris 767d2595cd Delete chroma.log 2025-04-28 09:20:31 +01:00
chris cfb3885afd Fix closing logic 2025-04-28 08:38:30 +01:00
Chris f6c23ab11a Fix merge conflict 2025-04-24 12:02:34 +01:00
Chris ca3a910401 Snippets 2025-04-24 12:01:48 +01:00
Chris 62b3b156fa More changes 2025-04-24 12:00:18 +01:00
chris c7d39fe79c Close vim if only non-file windows are open 2025-04-23 22:38:44 +01:00
chris bf83c416c5 Typo 2025-04-22 16:55:58 +01:00
chris 0940219a08 Only use Wakatime on mac 2025-04-15 21:03:11 +01:00
Chris eeb4e44367 Improved AI tools 2025-04-15 20:48:35 +01:00
Chris c3574de9bc First day of development changes 2025-04-14 15:20:54 +01:00
Chris 01164c6d8b More plugin configuration 2025-04-14 11:38:42 +01:00
chris f2f3b1812a Loads of changes 2025-04-13 22:53:08 +01:00
56 changed files with 4202 additions and 962 deletions
-1
View File
@@ -1 +0,0 @@
AIHUBMIX_API_KEY=
+391
View File
@@ -0,0 +1,391 @@
# Bash Cheat Sheet
## Conditionals
```bash
if [[ -z "$string" ]]; then
echo "String is empty"
elif [[ -n "$string" ]]; then
echo "String is not empty"
fi
```
### String conditions
┌────────────────────────┬──────────────────┐
`[[ -z STRING ]]` │ Empty string │
├────────────────────────┼──────────────────┤
`[[ -n STRING ]]` │ Not empty string │
├────────────────────────┼──────────────────┤
`[[ STRING == STRING ]]` │ Equal │
├────────────────────────┼──────────────────┤
`[[ STRING != STRING ]]` │ Not Equal │
├────────────────────────┼──────────────────┤
`[[ STRING =~ STRING ]]` │ Regex │
└────────────────────────┴──────────────────┘
### Number conditions
┌────────────────────────┬───────────────────────┐
`[[ NUM1 -eq NUM2 ]]` │ Equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -ne NUM2 ]]` │ Not Equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -lt NUM2 ]]` │ Less than │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -le NUM2 ]]` │ Less than or equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -gt NUM2 ]]` │ Greater than │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -ge NUM2 ]]` │ Greater than or equal │
├────────────────────────┼───────────────────────┤
`(( NUM < NUM ))` │ Numeric conditions │
└────────────────────────┴───────────────────────┘
### File conditions
┌───────────────────────┬─────────────────────────┐
`[[ -e FILE ]]` │ Exists │
├───────────────────────┼─────────────────────────┤
`[[ -r FILE ]]` │ Readable │
├───────────────────────┼─────────────────────────┤
`[[ -h FILE ]]` │ Symlink │
├───────────────────────┼─────────────────────────┤
`[[ -d FILE ]]` │ Directory │
├───────────────────────┼─────────────────────────┤
`[[ -w FILE ]]` │ Writable │
├───────────────────────┼─────────────────────────┤
`[[ -s FILE ]]` │ Size is > 0 bytes │
├───────────────────────┼─────────────────────────┤
`[[ -f FILE ]]` │ File │
├───────────────────────┼─────────────────────────┤
`[[ -x FILE ]]` │ Executable │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -nt FILE2 ]]` │ 1 is more recent than 2 │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -ot FILE2 ]]` │ 2 is more recent than 1 │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -ef FILE2 ]]` │ Same files │
└───────────────────────┴─────────────────────────┘
### Other conditions
┌────────────────────┬────────────────────┐
`[[ -o noclobber ]]` │ Option enabled │
├────────────────────┼────────────────────┤
`[[ ! EXPR ]]` │ Not │
├────────────────────┼────────────────────┤
`[[ X && Y ]]` │ And │
├────────────────────┼────────────────────┤
`[[ X || Y ]]` │ Or │
└────────────────────┴────────────────────┘
## Parameter manipulation
┌─────────────────────────────────┬────────────────────────────────────────────────────────────────┐
`${foo}` │ Variable │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo/from/to}` │ Replace first match │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo/#from/to}`/`${foo/%from/to}` │ Replace first match anchored to start (default) or end │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo//from/to}` │ Replace all │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:start:length}` │ Slice from `start` to `length` (both optional and can be negative) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo%suffix}`/`${foo%%suffix}` │ Remove `suffix` (ungreedy/greedy) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo#prefix}`/`${foo##prefix}` │ Remove `prefix` (ungreedy/greedy) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${#foo}` │ Length of `foo`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo,}` │ Lowercase first letter │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo,,}` │ Lowercase all letters │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo^}` │ Uppercase first letter │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo^^}` │ Uppercase all letters │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:-val}` │ Use `val` if `foo` is unset or null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:=val}` │ Set `foo` to `val` if unset or null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:+val}` │ Use `val` if `foo` **is** set and not null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:?message}` │ Print `message` and exit if `foo` is unset or null │
└─────────────────────────────────┴────────────────────────────────────────────────────────────────┘
> Omitting the `:` for default values will only check if the variable is set, not if it is null.
### Examples
```bash
name="John"
echo "${name}"
echo "${name/J/j}" #=> "john" (substitution)
echo "${name:0:2}" #=> "Jo" (slicing)
echo "${name::2}" #=> "Jo" (slicing)
echo "${name::-1}" #=> "Joh" (slicing)
echo "${name:(-1)}" #=> "n" (slicing from right)
echo "${name:(-2):1}" #=> "h" (slicing from right)
echo "${food:-Cake}" #=> $food or "Cake"
length=2
echo "${name:0:length}" #=> "Jo" (slicing with variable)
str="/path/to/foo.cpp"
echo "${str%.cpp}" # /path/to/foo
echo "${str%.cpp}.o" # /path/to/foo.o
echo "${str%/*}" # /path/to
echo "${str##*.}" # cpp (extension)
echo "${str##*/}" # foo.cpp (basepath)
echo "${str#*o}" # o/foo.cpp (first occurrence of 'o')
echo "${str##*o}" # oo.cpp (last occurrence of 'o')
echo "${str#*/}" # path/to/foo.cpp
echo "${str##*/}" # foo.cpp
echo "${str/foo/bar}" # /path/to/bar.cpp
str="HELLO WORLD!"
echo "${str,}" #=> "hELLO WORLD!" (lowercase 1st letter)
echo "${str,,}" #=> "hello world!" (all lowercase)
str="hello world!"
echo "${str^}" #=> "Hello world!" (uppercase 1st letter)
echo "${str^^}" #=> "HELLO WORLD!" (all uppercase)
```
## Comments
```bash
# This is a comment
: '
This is a multi-line comment workaround
'
```
## Loops
### Basic for loop
```bash
for i in /etc/rc.*; do
echo "$i"
done
```
### C-style for loop
```bash
for (( i = 0; i < 10; i++ )); do
echo "$i"
done
```
### Ranges
```bash
for i in {1..10}; do
echo "$i"
done
# With step size
for i in {1..10..2}; do
echo "$i"
done
```
### Reading lines
```bash
while IFS= read -r line; do
echo "$line"
done < file.txt
```
### Infinite loop
```bash
while true; do
echo "Press [CTRL+C] to stop.."
sleep 1
done
```
## History
┌───────────────┬────────────────────────────────────────────────────────────────┐
`!!` │ Expand latest command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$` │ Expand last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!*` │ Expand all parameters of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!-n` │ Expand nth latest command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!n` │ Expand nth command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!string` │ Expand latest command starting with string │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:s/from/to` │ Replace first occurrence of "from" with "to" in latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:gs/from/to` │ Replace all occurrences of "from" with "to" in latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:p` │ Print latest command without executing it │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$:t` │ Expand basename of last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$:h` │ Expand directory of last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n` │ Expand only nth parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!^` │ Expand first parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$` │ Expand last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n-m` │ Expand parameters from nth to mth of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n-$` │ Expand parameters from nth to last of latest command │
└───────────────┴────────────────────────────────────────────────────────────────┘
## Redirection
┌────────────────────────────┬─────────────────────────────────┐
`SCRIPT > FILE` │ stdout to FILE │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT >> FILE` │ Append stdout to FILE │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT 2> FILE` │ stderr to FILE │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT 2>&1`/`SCRIPT &> FILE` │ stderr to stdout │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT 2> /dev/null` │ stderr to /dev/null │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT > FILE 2>&1` │ stdout and stderr to FILE │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT &> /dev/null` │ stdout and stderr to /dev/null │
├────────────────────────────┼─────────────────────────────────┤
`echo "$0: warning" >&2` │ Print to stderr │
├────────────────────────────┼─────────────────────────────────┤
`SCRIPT < FILE` │ stdin from FILE │
└────────────────────────────┴─────────────────────────────────┘
## Switch statement
```bash
case "$1" in
start | up)
vagrant up
;;
*)
echo "Usage: $0 {start|stop|ssh}"
;;
esac
```
### Options switch statement
```bash
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
-V | --version )
echo "$version"
exit
;;
-s | --string )
shift; string=$1
;;
-f | --flag )
flag=1
;;
esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi
```
## Functions
```bash
my_function() {
echo "Hello, World!"
}
```
### Arguments
┌────┬───────────────────────────────────┐
`$#` │ Number of arguments │
├────┼───────────────────────────────────┤
`$*` │ All arguments │
├────┼───────────────────────────────────┤
`$@` │ All arguments as separate strings │
├────┼───────────────────────────────────┤
`$1` │ First argument │
├────┼───────────────────────────────────┤
`$_` │ Last argument │
└────┴───────────────────────────────────┘
## Arrays
```bash
# Create an array in one line
Fruits=('Apple' 'Banana' 'Orange')
# Or assign each value
Fruits[0]="Apple"
Fruits[1]="Banana"
Fruits[2]="Orange"
# Associative array
declare -A sounds
sounds[dog]="bark"
sounds[cow]="moo"
sounds[bird]="tweet"
sounds[wolf]="howl"
```
### Array element expansion
┌──────────────────────┬────────────────────────────────────────────────────┐
`${array[key]}` │ Element at `key`
├──────────────────────┼────────────────────────────────────────────────────┤
`${array[-1]}` │ Last element (not for associative) │
├──────────────────────┼────────────────────────────────────────────────────┤
`${array[@]}` │ All elements │
├──────────────────────┼────────────────────────────────────────────────────┤
`${#array[@]}` │ Number of elements │
├──────────────────────┼────────────────────────────────────────────────────┤
`${#array}` │ String length of 1st element (not for associative) │
├──────────────────────┼────────────────────────────────────────────────────┤
`${#array[key]}` │ String length of element at `key`
├──────────────────────┼────────────────────────────────────────────────────┤
`${array[@]:n:length}``length` eements from position `n`
├──────────────────────┼────────────────────────────────────────────────────┤
`${!array[@]}` │ Keys of all elements │
└──────────────────────┴────────────────────────────────────────────────────┘
### Operations
```bash
Fruits=("${Fruits[@]}" "Watermelon") # Push
Fruits+=('Watermelon') # Also Push
Fruits=( "${Fruits[@]/Ap*/}" ) # Remove by regex match
unset Fruits[2] # Remove one item
Fruits=("${Fruits[@]}") # Duplicate
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate
words=($(< datafile)) # From file (split by IFS)
```
### Looping
```bash
for i in "${Fruits[@]}"; do
echo "$i"
done
for key in "${!sounds[@]}"; do
echo "$key"
done
```
## Misc
### Directory of script
```bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
```
### Special variables
┌──────────────────┬────────────────────────────────────────┐
`$?` │ Exit status of last task │
├──────────────────┼────────────────────────────────────────┤
`$!` │ PID of last background task │
├──────────────────┼────────────────────────────────────────┤
`$$` │ PID of shell │
├──────────────────┼────────────────────────────────────────┤
`$0` │ Filename of the shell script │
├──────────────────┼────────────────────────────────────────┤
`$_` │ Last arugment of altest command │
├──────────────────┼────────────────────────────────────────┤
`${PIPESTATUS[n]}` │ Return value of piped commands (array) │
└──────────────────┴────────────────────────────────────────┘
+205
View File
@@ -0,0 +1,205 @@
# Regex Cheat Sheet
## Anchors
┌────┬─────────────────────────────────────────────────────────┐
│ ^ │ Start of string, or start of line in multi-line pattern │
├────┼─────────────────────────────────────────────────────────┤
│ \A │ Start of string │
├────┼─────────────────────────────────────────────────────────┤
│ $ │ End of string, or end of line in multi-line pattern │
├────┼─────────────────────────────────────────────────────────┤
│ \Z │ End of string │
├────┼─────────────────────────────────────────────────────────┤
│ \b │ Word boundary │
├────┼─────────────────────────────────────────────────────────┤
│ \B │ Not word boundary │
├────┼─────────────────────────────────────────────────────────┤
│ \< │ Start of word │
├────┼─────────────────────────────────────────────────────────┤
│ \> │ End of word │
└────┴─────────────────────────────────────────────────────────┘
## Character Classes
┌────┬────────────────────┐
│ \c │ Control character │
├────┼────────────────────┤
│ \s │ White space │
├────┼────────────────────┤
│ \S │ Not white space │
├────┼────────────────────┤
│ \d │ Digit │
├────┼────────────────────┤
│ \D │ Not digit │
├────┼────────────────────┤
│ \w │ Word │
├────┼────────────────────┤
│ \W │ Not word │
├────┼────────────────────┤
│ \x │ Hexadecimal digit │
├────┼────────────────────┤
│ \O │ Octal digit │
└────┴────────────────────┘
## POSIX
┌───────────┬───────────────────────────────┐
`[:upper:]` │ Upper case letters │
├───────────┼───────────────────────────────┤
`[:lower:]` │ Lower case letters │
├───────────┼───────────────────────────────┤
`[:alpha:]` │ All letters │
├───────────┼───────────────────────────────┤
`[:alnum:]` │ Digits and letters │
├───────────┼───────────────────────────────┤
`[:digit:]` │ Digits │
├───────────┼───────────────────────────────┤
`[:xdigit:]`│ Hexadecimal digits │
├───────────┼───────────────────────────────┤
`[:punct:]` │ Punctuation │
├───────────┼───────────────────────────────┤
`[:blank:]` │ Space and tab │
├───────────┼───────────────────────────────┤
`[:space:]` │ Blank characters │
├───────────┼───────────────────────────────┤
`[:cntrl:]` │ Control characters │
├───────────┼───────────────────────────────┤
`[:graph:]` │ Printed characters │
├───────────┼───────────────────────────────┤
`[:print:]` │ Printed characters and spaces │
├───────────┼───────────────────────────────┤
`[:word:]` │ Digits, letters and underscore│
└───────────┴───────────────────────────────┘
## Assertions
┌──────┬──────────────────────────────┐
│ ?= │ Lookahead assertion │
├──────┼──────────────────────────────┤
│ ?! │ Negative lookahead │
├──────┼──────────────────────────────┤
│ ?<= │ Lookbehind assertion │
├──────┼──────────────────────────────┤
│ ?!= │ Negative lookbehind │
│ ?<! │ │
├──────┼──────────────────────────────┤
│ ?> │ Once-only subexpression │
├──────┼──────────────────────────────┤
│ ?() │ Condition `[if then]`
├──────┼──────────────────────────────┤
│ ?()| │ Condition `[if then else]`
├──────┼──────────────────────────────┤
│ ?# │ Comment │
└──────┴──────────────────────────────┘
## Quantifiers
┌───────┬─────────────┐
│ * │ 0 or more │
├───────┼─────────────┤
│ + │ 1 or more │
├───────┼─────────────┤
│ ? │ 0 or 1 │
├───────┼─────────────┤
│ {3} │ Exactly 3 │
├───────┼─────────────┤
│ {3,} │ 3 or more │
├───────┼─────────────┤
│ {3,5} │ 3, 4 or 5 │
└───────┴─────────────┘
> Add a `?` to a quantifier to make it ungreedy.
## Escape Sequences
┌────┬─────────────────────────────┐
│ \ │ Escape following character │
├────┼─────────────────────────────┤
│ \Q │ Begin literal sequence │
├────┼─────────────────────────────┤
│ \E │ End literal sequence │
└────┴─────────────────────────────┘
> "Escaping" is a way of treating characters which have a special meaning in regular expressions literally, rather than as special characters.
## Common Metacharacters
┌───┬───┬───┬───┐
│ ^ │ [ │ . │ $ │
├───┼───┼───┼───┤
│ { │ * │ ( │ \ │
├───┼───┼───┼───┤
│ + │ ) │ | │ ? │
├───┼───┼───┼───┤
│ < │ > │ │ │
└───┴───┴───┴───┘
> The escape character is usually `\`.
## Special Characters
┌──────┬────────────────────┐
│ \n │ New line │
├──────┼────────────────────┤
│ \r │ Carriage return │
├──────┼────────────────────┤
│ \t │ Tab │
├──────┼────────────────────┤
│ \v │ Vertical tab │
├──────┼────────────────────┤
│ \f │ Form feed │
├──────┼────────────────────┤
│ \xxx │ Octal character xxx│
├──────┼────────────────────┤
│ \xhh │ Hex character hh │
└──────┴────────────────────┘
## Groups and Ranges
┌─────────┬────────────────────────────────────┐
│ . │ Any character except new line (\n) │
├─────────┼────────────────────────────────────┤
│ (a|b) │ a or b │
├─────────┼────────────────────────────────────┤
│ (...) │ Group │
├─────────┼────────────────────────────────────┤
│ (?:...) │ Passive (non-capturing) group │
├─────────┼────────────────────────────────────┤
`[abc]` │ Range (a or b or c) │
├─────────┼────────────────────────────────────┤
`[^abc]` │ Not (a or b or c) │
├─────────┼────────────────────────────────────┤
`[a-q]` │ Lower case letter from a to q │
├─────────┼────────────────────────────────────┤
`[A-Q]` │ Upper case letter from A to Q │
├─────────┼────────────────────────────────────┤
`[0-7]` │ Digit from 0 to 7 │
├─────────┼────────────────────────────────────┤
│ \x │ Group/subpattern number "x" │
└─────────┴────────────────────────────────────┘
> Ranges are inclusive.
## Pattern Modifiers
┌────┬────────────────────────────────────┐
│ g │ Global match │
├────┼────────────────────────────────────┤
│ i │ Case-insensitive │
├────┼────────────────────────────────────┤
│ m │ Multiple lines │
├────┼────────────────────────────────────┤
│ s │ Treat string as single line │
├────┼────────────────────────────────────┤
│ x │ Allow comments and whitespace │
├────┼────────────────────────────────────┤
│ e │ Evaluate replacement │
├────┼────────────────────────────────────┤
│ U │ Ungreedy pattern │
└────┴────────────────────────────────────┘
> * PCRE modifier
## String Replacement
┌────┬──────────────────────────────────┐
`$n` │ nth non-passive group │
├────┼──────────────────────────────────┤
`$2` │ "xyz" in `/^(abc(xyz))$/`
├────┼──────────────────────────────────┤
`$1` │ "xyz" in `/^(?:abc)(xyz)$/`
├────┼──────────────────────────────────┤
`$`` │ Before matched string │
├────┼──────────────────────────────────┤
│ `$'` │ After matched string │
├────┼──────────────────────────────────┤
│ `$+` │ Last matched string │
├────┼──────────────────────────────────┤
│ `$&` │ Entire matched string │
└────┴──────────────────────────────────┘
> Some regex implementations use `\` instead of `$`.
+437
View File
@@ -0,0 +1,437 @@
# ZSH Cheat Sheet
## Conditionals
```zsh
if [[ -z "$string" ]]; then
echo "String is empty"
elif [[ -n "$string" ]]; then
echo "String is not empty"
fi
```
### String conditions
┌────────────────────────┬──────────────────┐
`[[ -z STRING ]]` │ Empty string │
├────────────────────────┼──────────────────┤
`[[ -n STRING ]]` │ Not empty string │
├────────────────────────┼──────────────────┤
`[[ STRING == STRING ]]` │ Equal │
├────────────────────────┼──────────────────┤
`[[ STRING != STRING ]]` │ Not Equal │
├────────────────────────┼──────────────────┤
`[[ STRING =~ STRING ]]` │ Regex │
└────────────────────────┴──────────────────┘
### Number conditions
┌────────────────────────┬───────────────────────┐
`[[ NUM1 -eq NUM2 ]]` │ Equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -ne NUM2 ]]` │ Not Equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -lt NUM2 ]]` │ Less than │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -le NUM2 ]]` │ Less than or equal │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -gt NUM2 ]]` │ Greater than │
├────────────────────────┼───────────────────────┤
`[[ NUM1 -ge NUM2 ]]` │ Greater than or equal │
├────────────────────────┼───────────────────────┤
`(( NUM < NUM ))` │ Numeric conditions │
└────────────────────────┴───────────────────────┘
### File conditions
┌───────────────────────┬─────────────────────────┐
`[[ -e FILE ]]` │ Exists │
├───────────────────────┼─────────────────────────┤
`[[ -r FILE ]]` │ Readable │
├───────────────────────┼─────────────────────────┤
`[[ -h FILE ]]` │ Symlink │
├───────────────────────┼─────────────────────────┤
`[[ -d FILE ]]` │ Directory │
├───────────────────────┼─────────────────────────┤
`[[ -w FILE ]]` │ Writable │
├───────────────────────┼─────────────────────────┤
`[[ -s FILE ]]` │ Size is > 0 bytes │
├───────────────────────┼─────────────────────────┤
`[[ -f FILE ]]` │ File │
├───────────────────────┼─────────────────────────┤
`[[ -x FILE ]]` │ Executable │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -nt FILE2 ]]` │ 1 is more recent than 2 │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -ot FILE2 ]]` │ 2 is more recent than 1 │
├───────────────────────┼─────────────────────────┤
`[[ FILE1 -ef FILE2 ]]` │ Same files │
└───────────────────────┴─────────────────────────┘
### Other conditions
┌────────────────────┬────────────────────┐
`[[ -o noclobber ]]` │ Option enabled │
├────────────────────┼────────────────────┤
`[[ ! EXPR ]]` │ Not │
├────────────────────┼────────────────────┤
`[[ X && Y ]]` │ And │
├────────────────────┼────────────────────┤
`[[ X || Y ]]` │ Or │
└────────────────────┴────────────────────┘
## Parameter manipulation
┌─────────────────────────────────┬────────────────────────────────────────────────────────────────┐
`${foo}` │ Variable │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo/from/to}` │ Replace first match │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo/#from/to}`/`${foo/%from/to}` │ Replace first match anchored to start (default) or end │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo//from/to}` │ Replace all │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo[start,length]}` │ Slice from `start` to `length` (`length` can be negative) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo%suffix}`/`${foo%%suffix}` │ Remove `suffix` (ungreedy/greedy) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo#prefix}`/`${foo##prefix}` │ Remove `prefix` (ungreedy/greedy) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${#foo}` │ Length of `foo`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(L)foo}` │ Lowercase all letters │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(U)foo}` │ Uppercase all letters │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(q)foo}` │ Quote safely │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(qq)foo}` │ Quote more explicitely │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(s.del.)foo}` │ Split on `del`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${(j.del.)foo}` │ Join with `del`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:h}` │ Directory of `file`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:t}` │ Filename of `file`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:e}` │ Extension of `file`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:r}` │ Root of `file` (without extension) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:a}` │ Absolute path of `file`
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${file:A}` │ Absolute path of `file` (resolves symlinks) │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:-val}` │ Use `val` if `foo` is unset or null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:=val}` │ Set `foo` to `val` if unset or null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:+val}` │ Use `val` if `foo` **is** set and not null │
├─────────────────────────────────┼────────────────────────────────────────────────────────────────┤
`${foo:?message}` │ Print `message` and exit if `foo` is unset or null │
└─────────────────────────────────┴────────────────────────────────────────────────────────────────┘
> Omitting the `:` for default values will only check if the variable is set, not if it is null.
### Examples
```zsh
name="John"
echo "${name}"
echo "${name/J/j}" #=> "john" (substitution)
echo "${name[0,2]}" #=> "Jo" (slicing)
echo "${food:-Cake}" #=> $food or "Cake"
length=2
echo "${name[1,length]}" #=> "Jo" (slicing with variable)
str="/path/to/foo.cpp"
echo "${str%.cpp}" # /path/to/foo
echo "${str%.cpp}.o" # /path/to/foo.o
echo "${str%/*}" # /path/to
echo "${str##*.}" # cpp (extension)
echo "${str##*/}" # foo.cpp (basepath)
echo "${str#*o}" # o/foo.cpp (first occurrence of 'o')
echo "${str##*o}" # oo.cpp (last occurrence of 'o')
echo "${str#*/}" # path/to/foo.cpp
echo "${str##*/}" # foo.cpp
echo "${str/foo/bar}" # /path/to/bar.cpp
str="HELLO WORLD!"
echo "${(L)str}" #=> "hello world!" (all lowercase)
str="hello world!"
echo "${(U)str}" #=> "HELLO WORLD!" (all uppercase)
```
## Globs
┌───────────────┬───────────────────────┐
`ls **/*.js` │ Recursive expansion │
├───────────────┼───────────────────────┤
`ls *(.)` │ Plain files │
├───────────────┼───────────────────────┤
`ls *(/)` │ Directories │
├───────────────┼───────────────────────┤
`ls *(@)` │ Symlinks │
├───────────────┼───────────────────────┤
`ls *(*)` │ Executables │
├───────────────┼───────────────────────┤
`ls *(L+1M)` │ Files larger than 1MB │
├───────────────┼───────────────────────┤
`ls *(om[1,5])` │ 5 newest files │
├───────────────┼───────────────────────┤
`ls *(.)~*.bak` │ Files except *.bak │
└───────────────┴───────────────────────┘
## Comments
```zsh
# This is a comment
: '
This is a multi-line comment workaround
'
```
## Loops
### Basic for loop
```zsh
for i in /etc/rc.*; do
echo "$i"
done
```
### C-style for loop
```zsh
for (( i = 0; i < 10; i++ )); do
echo "$i"
done
```
### Ranges
```zsh
for i in {1..10}; do
echo "$i"
done
# With step size
for i in {1..10..2}; do
echo "$i"
done
```
### Reading lines
```zsh
while IFS= read -r line; do
print -r -- "$line"
done < file.txt
```
### Infinite loop
```zsh
while true; do
echo "Press [CTRL+C] to stop.."
sleep 1
done
```
## History
┌───────────────┬────────────────────────────────────────────────────────────────┐
`!!` │ Expand latest command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$` │ Expand last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!*` │ Expand all parameters of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!-n` │ Expand nth latest command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!n` │ Expand nth command in history │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!string` │ Expand latest command starting with string │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:s/from/to` │ Replace first occurrence of "from" with "to" in latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:gs/from/to` │ Replace all occurrences of "from" with "to" in latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:p` │ Print latest command without executing it │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$:t` │ Expand basename of last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$:h` │ Expand directory of last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n` │ Expand only nth parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!^` │ Expand first parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!$` │ Expand last parameter of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n-m` │ Expand parameters from nth to mth of latest command │
├───────────────┼────────────────────────────────────────────────────────────────┤
`!!:n-$` │ Expand parameters from nth to last of latest command │
└───────────────┴────────────────────────────────────────────────────────────────┘
## Redirection
┌────────────────────────┬─────────────────────────────────┐
`SCRIPT > FILE` │ stdout to FILE │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT >> FILE` │ Append stdout to FILE │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT 2> FILE` │ stderr to FILE │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT 2>&1` │ stderr to stdout │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT &> FILE` │ stderr and stdout to FILE │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT 2> /dev/null` │ stderr to /dev/null │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT > FILE 2>&1` │ stdout and stderr to FILE │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT &> /dev/null` │ stdout and stderr to /dev/null │
├────────────────────────┼─────────────────────────────────┤
`echo "$0: warning" >&2` │ Print to stderr │
├────────────────────────┼─────────────────────────────────┤
`SCRIPT < FILE` │ stdin from FILE │
└────────────────────────┴─────────────────────────────────┘
## Switch statement
```zsh
case "$1" in
start | up)
vagrant up
;;
*)
echo "Usage: $0 {start|stop|ssh}"
;;
esac
```
### Options switch statement
```zsh
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
-V | --version )
echo "$version"
exit
;;
-s | --string )
shift; string=$1
;;
-f | --flag )
flag=1
;;
esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi
```
## Functions
```zsh
my_function() {
echo "Hello, World!"
}
```
### Arguments
┌────┬───────────────────────────────────┐
`$#` │ Number of arguments │
├────┼───────────────────────────────────┤
`$*` │ All arguments │
├────┼───────────────────────────────────┤
`$@` │ All arguments as separate strings │
├────┼───────────────────────────────────┤
`$1` │ First argument │
├────┼───────────────────────────────────┤
`$_` │ Last argument │
└────┴───────────────────────────────────┘
## Arrays
```zsh
# Create an array in one line
Fruits=('Apple' 'Banana' 'Orange')
# Or assign each value
Fruits[1]="Apple"
Fruits[2]="Banana"
Fruits[3]="Orange"
# Associative array
typeset -A sounds
sounds[dog]="bark"
sounds[cow]="moo"
sounds[bird]="tweet"
sounds[wolf]="howl"
```
### Array element expansion
┌──────────────────────────────────────┬────────────────────────────────────┐
`${array[key]}` │ Element at `key`
├──────────────────────────────────────┼────────────────────────────────────┤
`${array[-1]}` │ Last element (not for associative) │
├──────────────────────────────────────┼────────────────────────────────────┤
`${array[@]}` │ All elements │
├──────────────────────────────────────┼────────────────────────────────────┤
`${#array}` │ Number of elements │
├──────────────────────────────────────┼────────────────────────────────────┤
`${#array[key]}` │ String length of element at `key`
├──────────────────────────────────────┼────────────────────────────────────┤
`${array:n:length}`/`${array[n,length]}``length` eements from position `n`
├──────────────────────────────────────┼────────────────────────────────────┤
`${(k)array}` │ Keys of all elements │
└──────────────────────────────────────┴────────────────────────────────────┘
### Operations
```zsh
Fruits=("${Fruits[@]}" "Watermelon") # Push
Fruits+=('Watermelon') # Also Push
Fruits=( "${Fruits[@]/Ap*/}" ) # Remove by regex match
unset Fruits[3] # Remove one item
Fruits=("${Fruits[@]}") # Duplicate
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate
words=($(< datafile)) # From file (split by IFS)
```
### Looping
```zsh
for i in "${Fruits[@]}"; do
echo "$i"
done
for val in "${(v)sounds}"; do
echo "$val"
done
for key in "${(k)sounds}"; do
echo "$key"
done
```
## Misc
### Directory of script
```zsh
DIR="$( cd "$( dirname "${ZSH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
```
### Special variables
┌──────────────────┬───────────────────────────────────────────────┐
`$?` │ Exit status of last task │
├──────────────────┼───────────────────────────────────────────────┤
`$!` │ PID of last background task │
├──────────────────┼───────────────────────────────────────────────┤
`$$` │ PID of shell │
├──────────────────┼───────────────────────────────────────────────┤
`$#` │ Number of arguments passed to script │
├──────────────────┼───────────────────────────────────────────────┤
`$0` │ Filename of the shell script │
├──────────────────┼───────────────────────────────────────────────┤
`$_` │ Last arugment of altest command │
├──────────────────┼───────────────────────────────────────────────┤
`$argv` │ Array of all arguments passed to script │
├──────────────────┼───────────────────────────────────────────────┤
`$ARGC` │ Number of arguments passed to script │
├──────────────────┼───────────────────────────────────────────────┤
`${pipestatus[n]}` │ Return value of piped commands (array) │
├──────────────────┼───────────────────────────────────────────────┤
`$RANDOM` │ Random number between 0 and 32767 │
├──────────────────┼───────────────────────────────────────────────┤
`$SECONDS` │ Number of seconds since the shell was started │
├──────────────────┼───────────────────────────────────────────────┤
`$PWD` │ Current working directory │
├──────────────────┼───────────────────────────────────────────────┤
`$OLDPWD` │ Previous working directory │
└──────────────────┴───────────────────────────────────────────────┘
+29 -445
View File
@@ -1,6 +1,7 @@
-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
vim.lsp.log.set_level 'debug'
vim.g.mapleader = ','
vim.g.maplocalleader = ','
@@ -11,456 +12,38 @@ require 'opt'
require 'keymap'
require 'autocmd'
require 'lazy_init'
require 'visuals'
require 'projects'
-- nnoremap <Leader>ev :tabedit $MYVIMRC<CR>
require('helpers').edit_cf('v', '/init.lua')
-- The line beneath this is called `modeline`. See `:help modeline`
-- vim: ts=2 sts=2 sw=2 et
--[[
TODO: Neovim configurations I want to add:
- [x] Clearer line numbers (weirdly not as simple as it sounds)
- [ ] Debugging keymap that works like PHPStorm
- [ ] Improve snippet expansion (and get rid of that stupid #endsection snippet)
- [ ] Better organising of buffers when opening side panels (like AI chat and test summary)
- [ ] Close test panel when opening debugger and vice versa using edgy
- [ ] Close terminal from inside terminal buffer
- [ ] Get shift key bindings working inside tmux
- [ ] Fix ctrl+shift+a keybinding for AI actions
- [ ] Get VectorCode working
- [ ] Add LSP symbols for Pest tests
- [ ] More prompts
- [ ] Give AI better context and tools for working with Hylark
- [ ] Figure out AI workspaces
- [ ] Figure out agentic workflow
- [ ] Figure out a better way to add relevant buffers to AI
- [ ] Better inline AI assistant
- [ ] Keymap to copy visual selection to chat
- [ ] Better register management
- [ ] Figure out debug expressions
- [ ] Better keymaps for debug movements
- [ ] Chat history
]]
-- " Mappings --- {{{
-- " Editing files - {{{
-- "Make it easy to edit the vimrc file
-- " }}}
--
-- "Changing unused ctrl bindings
-- "Turn on git blame
-- nnoremap <C-S-A> <CMD>Git blame<CR>
-- "List all tags in the current buffer (replaced pageup, use CTRL-u instead)
-- nnoremap <C-Q> <CMD>CocFzfList outline<CR>
-- "List all tags in directory
-- "nnoremap <C-S-B> <CMD>Tags<CR>
-- "List all the recently opened files (replaced scroll one line up, use "k")
-- nnoremap <C-E> <CMD>History<CR>
-- "Search within the current buffer (replaced pagedown, use CTRL-d instead)
-- "nnoremap <C-F> /
-- "Search within the whole project
-- nnoremap <C-F> <CMD>Rg<CR>
-- "Move line down (uses vim-unimpaired) (replaced move down, use "j")
-- nnoremap <C-J> <C-E>
-- "Move line up (uses vim-unimpaired) (replaced move up, use "k")
-- nnoremap <C-K> <C-Y>
-- "Does not work because of legacy reasons
-- " nnoremap <C-M>
-- "Search marks (replaced "j" clone)
-- nnoremap <C-N> <CMD>Marks<CR>
-- "Search version controlled files (replaced move up, use "k")
-- nnoremap <C-P> <CMD>GFiles<CR>
-- "Search all files in directory
-- nnoremap <C-S-P> <CMD>Files<CR>
-- "Toggle file draw
-- nnoremap <C-S-Q> <CMD>CHADopen<CR>
-- "Search all snippets (uses ultisnips)
-- nnoremap <C-S> <CMD>Snippets<CR>
-- "Search git history (replaced scroll one line up, use "k")
-- nnoremap <C-Y> <CMD>Commits<CR>
-- "Search git history within current buffer/selection
-- nnoremap <C-S-Y> <CMD>BCommits<CR>
--
-- "Turn on git blame
-- inoremap <C-S-A> <CMD>Git blame<CR>
-- "List all tags in the current buffer
-- inoremap <C-Q> <CMD>BTags<CR>
-- "List all tags in directory
-- inoremap <C-S-Q> <CMD>Tags<CR>
-- "List all the recently opened files (replaced inserting characters from below)
-- inoremap <C-E> <CMD>History<CR>
-- "Search within the current buffer
-- inoremap <C-F> <Esc>/
-- "Search within the whole project
-- inoremap <C-S-F> <CMD>Rg<CR>
-- "Move line down (uses vim-unimpaired) (replaced <CR> clone)
-- inoremap <C-J> <Esc>ddpi
-- "Move line up (uses vim-unimpaired) (replaced start digraph, use command instead)
-- inoremap <C-K> <Esc>ddkPi
-- "Does not work because of legacy reasons
-- " inoremap <C-M> <CMD>Marks<CR>
-- "Add line below (replaced execute single command in normal)
-- inoremap <C-O> <Esc>o
-- "Add line above
-- inoremap <C-S-O> <Esc>O
-- "Search version controlled files (replaced autocomplete reverse)
-- inoremap <C-P> <CMD>GFiles<CR>
-- "Search all files in directory
-- inoremap <C-S-P> <CMD>Files<CR>
-- "Toggle file draw (replaces CTRL-v clone)
-- inoremap <C-S-Q> <CMD>CHADopen<CR>
-- "Search all snippets (uses ultisnips)
-- inoremap <C-S> <CMD>Snippets<CR>
-- "Search git history (replaced inserting characters from above)
-- inoremap <C-Y> <CMD>Commits<CR>
-- "Search git history within current buffer/selection
-- inoremap <C-S-Y> <CMD>BCommits<CR>
--
-- "Add simple highlight removal
-- nnoremap <Leader><Space> :nohlsearch<CR>
--
-- "Convert tabs to spaces
-- nnoremap <Leader><Tab> :retab<CR>
--
-- "Git mappings
-- nnoremap ga :Git add %<CR>
-- nnoremap gb :Git blame<CR>
-- nnoremap gC :Git commit<CR>
-- nnoremap gp :Git push<CR>
-- nnoremap gP :Git pull<CR>
--
-- "Map movement keys to Escape
-- inoremap jj <Esc>
-- inoremap jk <Esc>
-- inoremap kk <Esc>
-- inoremap hh <Esc>
--
-- "Delete a line in insert mode
-- " inoremap <C-D> <Esc>ddi
--
-- "Use semicolon instead of colon for commands
-- nnoremap ; :
-- nnoremap : ;
--
-- "Append the line with a semicolon
-- inoremap <Leader>; <Esc>mzA;<Esc>`za
-- nnoremap <Leader>; mzA;<Esc>`za<Esc>
--
-- "Easily navigate items in the quickfix menu
-- nnoremap <Leader>] :cnext<CR>
-- nnoremap <Leader>[ :cprevious<CR>
--
-- "Indent arrays
-- nnoremap <Leader>{ mzF[`a<CR><Esc>``%i<CR><Esc>`z
-- nnoremap <Leader>} mzF[`a<CR><Esc>``%i<CR><Esc>`zvi[:s/,\s*/,\r/g<CR>vi[=<Esc>`z:nohlsearch<CR>
--
-- "A command to properly indent json code
-- command! FormatJSON %!python -m json.tool
--
-- " Allow saving of files as doas
-- command! W execute 'silent! w !doas /usr/bin/tee % >/dev/null' <BAR> edit!
-- command! X execute 'silent! x !doas /usr/bin/tee % >/dev/null' <BAR> edit!
--
-- " }}}
--
-- " Plugins --- {{{
--
-- " COC --- {{{
-- " Use tab for trigger completion with characters ahead and navigate
-- " NOTE: There's always complete item selected by default, you may want to enable
-- " no select by `"suggest.noselect": true` in your configuration file
-- " NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
-- " other plugin before putting this into your config
-- inoremap <silent><expr> <TAB>
-- \ coc#pum#visible() ? coc#pum#next(1) :
-- \ CheckBackspace() ? "\<Tab>" :
-- \ coc#refresh()
-- inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
--
-- " Make <CR> to accept selected completion item or notify coc.nvim to format
-- " <C-g>u breaks current undo, please make your own choice
-- inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
-- \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
--
-- function! CheckBackspace() abort
-- let col = col('.') - 1
-- return !col || getline('.')[col - 1] =~# '\s'
-- endfunction
--
-- if has('nvim')
-- inoremap <silent><expr> <c-space> coc#refresh()
-- else
-- inoremap <silent><expr> <c-@> coc#refresh()
-- endif
--
-- " Use `[g` and `]g` to navigate diagnostics
-- " Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
-- nmap <silent> [g <Plug>(coc-diagnostic-prev)
-- nmap <silent> ]g <Plug>(coc-diagnostic-next)
--
-- " GoTo code navigation
-- nmap <silent> gd <Plug>(coc-definition)
-- nmap <silent> gy <Plug>(coc-type-definition)
-- nmap <silent> gi <Plug>(coc-implementation)
-- nmap <silent> gr <Plug>(coc-references)
--
-- " Use K to show documentation in preview window
-- nnoremap <silent> K :call ShowDocumentation()<CR>
--
-- function! ShowDocumentation()
-- if CocAction('hasProvider', 'hover')
-- call CocActionAsync('doHover')
-- else
-- call feedkeys('K', 'in')
-- endif
-- endfunction
--
-- " Highlight the symbol and its references when holding the cursor
-- autocmd CursorHold * silent call CocActionAsync('highlight')
--
-- " Symbol renaming
-- nmap <leader>rn <Plug>(coc-rename)
--
-- " Formatting selected code
-- xmap <leader>f <Plug>(coc-format-selected)
-- nmap <leader>f <Plug>(coc-format-selected)
--
-- augroup mygroup
-- autocmd!
-- " Setup formatexpr specified filetype(s)
-- autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
-- " Update signature help on jump placeholder
-- autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
-- augroup end
--
-- " Applying code actions to the selected code block
-- " Example: `<leader>aap` for current paragraph
-- xmap <leader>a <Plug>(coc-codeaction-selected)
-- nmap <leader>a <Plug>(coc-codeaction-selected)
--
-- " Remap keys for applying code actions at the cursor position
-- nmap <leader>ac <Plug>(coc-codeaction-cursor)
-- " Remap keys for apply code actions affect whole buffer
-- nmap <leader>as <Plug>(coc-codeaction-source)
-- " Apply the most preferred quickfix action to fix diagnostic on the current line
-- nmap <leader>qf <Plug>(coc-fix-current)
--
-- " Remap keys for applying refactor code actions
-- nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
-- xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
-- nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
--
-- " Run the Code Lens action on the current line
-- nmap <leader>cl <Plug>(coc-codelens-action)
--
-- " Map function and class text objects
-- " NOTE: Requires 'textDocument.documentSymbol' support from the language server
-- xmap if <Plug>(coc-funcobj-i)
-- omap if <Plug>(coc-funcobj-i)
-- xmap af <Plug>(coc-funcobj-a)
-- omap af <Plug>(coc-funcobj-a)
-- xmap ic <Plug>(coc-classobj-i)
-- omap ic <Plug>(coc-classobj-i)
-- xmap ac <Plug>(coc-classobj-a)
-- omap ac <Plug>(coc-classobj-a)
--
-- " Remap <C-f> and <C-b> to scroll float windows/popups
-- " if has('nvim-0.4.0') || has('patch-8.2.0750')
-- " nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
-- " nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
-- " inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
-- " inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
-- " vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
-- " vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
-- " endif
--
-- " Use CTRL-S for selections ranges
-- " Requires 'textDocument/selectionRange' support of language server
-- nmap <silent> <C-s> <Plug>(coc-range-select)
-- xmap <silent> <C-s> <Plug>(coc-range-select)
--
-- " Add `:Format` command to format current buffer
-- command! -nargs=0 Format :call CocActionAsync('format')
--
-- " Add `:Fold` command to fold current buffer
-- command! -nargs=? Fold :call CocAction('fold', <f-args>)
--
-- " Add `:OR` command for organize imports of the current buffer
-- command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
--
-- " Add (Neo)Vim's native statusline support
-- " NOTE: Please see `:h coc-status` for integrations with external plugins that
-- " provide custom statusline: lightline.vim, vim-airline
-- set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
--
--
-- " Mappings for CoCList
-- " Show all diagnostics
-- nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
-- " Manage extensions
-- nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
-- " Show commands
-- nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
-- " Find symbol of current document
-- nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
-- " Search workspace symbols
-- nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
-- " Do default action for next item
-- nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
-- " Do default action for previous item
-- nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
-- " Resume latest coc list
-- nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
--
-- " }}}
--
-- " Emmet --- {{{
-- " Toggle emmet completion using <Tab> with <Leader>em
-- let g:emmet_completion = 0
-- function ToggleEmmet()
-- if g:emmet_completion
-- echo "Emmet completion off!"
-- let g:user_emmet_expandabbr_key=','
-- iunmap <Tab>
-- let g:emmet_completion = 0
-- else
-- echo "Emmet completion on!"
-- let g:user_emmet_expandabbr_key='<Tab>'
-- imap <Expr> <Tab> emmet#expandAbbrIntelligent("\<Tab>")
-- let g:emmet_completion = 1
-- endif
-- endfunction
-- nnoremap <Leader>em :call ToggleEmmet()<CR>
-- " }}}
--
-- " Markdown --- {{{
-- " Conceal markdown text
-- set conceallevel=3
-- " }}}
--
-- " AutoPairs --- {{{
-- let g:AutoPairsFlyMode = 0
-- let g:AutoPairsShortcutBackInsert = '<M-b>' " Use <M-B> to insert the closing parentheses if it jumped ahead by mistake
-- " }}}
--
-- " CHADTree --- {{{
-- let g:chadtree_settings = {
-- \ 'theme': {
-- \ 'icon_glyph_set': 'devicons',
-- \ 'text_colour_set': 'env',
-- \ 'icon_colour_set': 'github',
-- \ "discrete_colour_map": {
-- \ "black": "#21222c",
-- \ "red": "#ff5555",
-- \ "green": "#50fa7b",
-- \ "yellow": "#f1fa8c",
-- \ "blue": "#bd93f9",
-- \ "magenta": "#ff79c6",
-- \ "cyan": "#8be9fd",
-- \ "white": "#f8f8f2",
-- \ "bright_black": "#6272a4",
-- \ "bright_red": "#ff6e6e",
-- \ "bright_green": "#69ff94",
-- \ "bright_yellow": "#ffffa5",
-- \ "bright_blue": "#d6acff",
-- \ "bright_magenta": "#ff92df",
-- \ "bright_cyan": "#a4ffff",
-- \ "bright_white": "#ffffff"
-- \ }
-- \ }
-- \ }
-- " }}}
--
-- " Commentary --- {{{
-- " function s:set_commentary_format()
-- " echo "running command"
-- " if &filetype =~ 'vue\|html\|svelte'
-- " if searchpair('<\(script\|style\)', '', '</\(script\|style\)>', 'Wn')
-- " let b:commentary_format="// %s"
-- " else
-- " let b:commentary_format=&commentstring
-- " endif
-- " endif
-- " endfunction
--
-- " xnoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " onoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap gcc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap cgc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap cgu :call <SID>set_commentary_format()<CR><Plug>Commentary<Plug>Commentary
-- " }}}
--
-- " Easymotion --- {{{
-- let g:EasyMotion_do_mapping = 0 " Disable default mappings
--
-- map <Leader> <Plug>(easymotion-prefix)
-- " Jump to anywhere you want with minimal keystrokes, with just one key binding.
-- " `s{char}{label}
-- nmap s <Plug>(easymotion-overwin-f)
--
-- " Turn on case-insensitive feature
-- let g:EasyMotion_smartcase = 1
--
-- " JK motions: Line motions
-- map <Leader>j <Plug>(easymotion-j)
-- map <Leader>k <Plug>(easymotion-k)
-- " }}}
--
-- " }}}
--
-- " PHP --- {{{
-- " function! RunPHPUnitTest()
-- " cd %:p:h
-- " normal! T yw
-- " let result = system("phpunit --filter " . @" . " " . bufname("%"))
-- " split __PHPUnit_Result__
-- " normal! ggdG
-- " setlocal buftype=nofile
-- " call append(0, split(result, '\v\n'))
-- " cd -
-- " endfunction
--
-- " nnoremap <F12> :call RunPHPUnitTest()<cr>
-- " }}}
--
-- " Moving around --- {{{
-- "Use capital H and L to move to the start and end of lines
-- nnoremap H ^
-- nnoremap L $
--
-- " }}}
--
-- " Operator mappings --- {{{
-- onoremap in( :<C-U>normal! f(vi(<CR>
-- onoremap il( :<C-U>normal! F)vi(<CR>
-- onoremap an( :<C-U>normal! f(va(<CR>
-- onoremap al( :<C-U>normal! F)va(<CR>
-- onoremap an{ :<C-U>normal! f{vi{<CR>
-- onoremap al{ :<C-U>normal! F}vi<CR>
-- " }}}
--
-- " Abbreviations --- {{{
-- iabbrev adn and
-- iabbrev waht what
-- iabbrev tehn then
-- iabbrev tihs this
-- iabbrev teh the
-- iabbrev Teh The
-- " }}}
--
-- " Auto-Commands --- {{{
--
-- "Automatically source the config files on save.
-- augroup autosourcing
-- autocmd!
-- autocmd BufWritePost $MYVIMRC source % "Source the vimrc file
-- augroup END
--
-- "Fold vimrc and zshrc files on open
-- augroup autofolding
-- autocmd!
-- autocmd BufReadPost $MYVIMRC :setlocal foldlevelstart=0
-- autocmd FileType vim setlocal foldmethod=marker
-- autocmd BufReadPost zsh :setlocal foldlevelstart=0
-- autocmd FileType zsh setlocal foldmethod=marker
-- augroup END
--
-- "Set commentary formats
-- function s:setcommentary()
-- if &commentstring =~ '/\*\s*%s\s*\*/'
-- let b:commentary_format="// %s"
-- endif
-- endfunction
--
-- augroup autocomment
-- autocmd!
-- autocmd FileType * call <SID>setcommentary()
-- augroup END
--
-- "Automatically save files
-- augroup autosaving
-- autocmd!
-- autocmd FocusLost * silent! wa "Save all files when moving away from the window
-- autocmd InsertLeave * silent! wa "Save all files when leaving insert mode
-- autocmd TextChanged * silent! wa "Save all files when text is changed
-- augroup END
--
-- augroup modes
-- autocmd!
-- autocmd FocusLost * call feedkeys("\<Esc>") "Go to normal mode when moving away
@@ -480,3 +63,4 @@ require 'lazy_init'
-- " - To operate on multiple lines use <c-v> to select the lines, <c-i> to go to
-- " insert mode, perform edit, press <esc>.
-- " - Use the command :r to paste the output of a command to the buffer.
+223 -4
View File
@@ -4,12 +4,231 @@
-- Highlight when yanking (copying) text
-- Try it with `yap` in normal mode
-- See `:help vim.highlight.on_yank()`
vim.api.nvim_create_autocmd('TextYankPost', {
desc = 'Highlight when yanking (copying) text',
group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }),
vim.api.nvim_create_autocmd("TextYankPost", {
desc = "Highlight when yanking (copying) text",
group = vim.api.nvim_create_augroup("kickstart-highlight-yank", { clear = true }),
callback = function()
vim.highlight.on_yank()
end,
})
require('helpers').edit_cf('a', '/lua/autocmd.lua')
local autosave_group = vim.api.nvim_create_augroup("autosaving", { clear = true })
vim.api.nvim_create_autocmd("FocusLost", {
group = autosave_group,
pattern = "*",
command = "silent! wa", -- Save all files when moving away from the window
nested = true, -- Allow other autocommands to run after this one
})
vim.api.nvim_create_autocmd("BufLeave", {
group = autosave_group,
pattern = "*",
command = "silent! wa", -- Save all files when switching buffers
nested = true, -- Allow other autocommands to run after this one
})
vim.api.nvim_create_autocmd("SwapExists", {
desc = "Always choose to delete the swap file, files are saved automatically",
group = vim.api.nvim_create_augroup("NoSwaps", { clear = true }),
callback = function(args)
vim.cmd("let v:swapchoice = 'd'")
end,
})
-- vim.api.nvim_create_autocmd('TextChanged', {
-- group = autosave_group,
-- pattern = '*',
-- command = 'silent! wa', -- Save all files when text is changed
-- })
vim.api.nvim_create_autocmd("User", {
pattern = "OilActionsPost",
callback = function(event)
if event.data.actions.type == "move" then
Snacks.rename.on_rename_file(event.data.actions.src_url, event.data.actions.dest_url)
end
end,
})
local fidget_group = vim.api.nvim_create_augroup("CodeCompanionFidgetHooks", { clear = true })
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestStarted",
group = fidget_group,
callback = function(event)
local FidgetHelper = require("utils.fidget_helper")
-- Pass event instead of request if the callback receives the full event object
local handle = FidgetHelper:create_progress_handle(event)
FidgetHelper:store_progress_handle(event.data.id, handle)
end,
})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestFinished",
group = fidget_group,
callback = function(event)
local FidgetHelper = require("utils.fidget_helper")
local handle = FidgetHelper:pop_progress_handle(event.data.id)
if handle then
FidgetHelper:report_exit_status(handle, event)
handle:finish()
end
end,
})
-- vim.api.nvim_create_autocmd('BufEnter', {
-- callback = function(event)
-- local windows = vim.api.nvim_list_wins()
--
-- for _, window in ipairs(windows) do
-- local bufnr = vim.api.nvim_win_get_buf(window)
-- local ft = vim.api.nvim_get_option_value('filetype', { buf = bufnr })
-- if vim.api.nvim_get_option_value('buflisted', { buf = bufnr })
-- or ft == 'oil'
-- or ft == 'snacks_dashboard' then
-- return
-- end
-- end
-- vim.cmd 'qa'
-- end,
-- })
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
pattern = { "*.lua" },
callback = function(args)
require("helpers").format_buffer("stylua", args.buf)
end,
})
local modes_group = vim.api.nvim_create_augroup("modes", { clear = true })
vim.api.nvim_create_autocmd("FocusLost", {
group = modes_group,
pattern = "*",
command = 'call feedkeys("\\<Esc>")',
})
vim.api.nvim_create_autocmd("BufNewFile", {
group = modes_group,
pattern = "*",
command = 'call feedkeys("i")',
})
-- Reload LuaSnip snippets when saving files in the snippets directory
local snippets_dir = vim.fn.stdpath("config") .. "/lua/snippets"
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = snippets_dir .. "/*.json", -- Adjust the path to match your snippets directory
desc = "Reload LuaSnip snippets on save",
callback = function()
require("luasnip.loaders.from_vscode").lazy_load({ paths = { snippets_dir } })
vim.notify("Snippets reloaded!", vim.log.levels.INFO)
end,
})
-- Run shortcuts script when saving shortcut files
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = {
os.getenv("XDG_CONFIG_HOME") .. "/shell/bm-files",
os.getenv("XDG_CONFIG_HOME") .. "/shell/bm-dirs",
},
desc = "Run shortcuts script",
callback = function()
os.execute("station-shortcuts")
vim.notify("Shortcuts updated!", vim.log.levels.INFO)
end,
})
local configs = {
{
path = os.getenv("HOME") .. "/.config/nixos",
worktree = nil,
git_dir = nil,
track_untracked = false,
force_add = false,
},
{
path = os.getenv("HOME") .. "/.config/nvim",
worktree = nil,
git_dir = nil,
track_untracked = false,
force_add = false,
},
{
path = os.getenv("HOME"),
worktree = os.getenv("HOME"),
git_dir = os.getenv("HOME") .. "/.config/dotfiles/.git",
track_untracked = true,
force_add = true, -- Handles ignored files in dotfiles
include_dirs = { ".config", ".local/bin", ".local/share" },
},
}
local function get_git_status(config)
local base = "git"
if config.git_dir and config.worktree then
base = string.format("git --git-dir=%s --worktree=%s", config.git_dir, config.worktree)
end
-- Check modified and untracked (including ignored if force_add is true)
local cmd = base .. " status --porcelain"
if config.force_add then
cmd = cmd .. " --ignored"
end
local handle = io.popen(cmd)
local result = handle:read("*a")
handle:close()
local has_changes = false
for line in result:gmatch("[^\r\n]+") do
local status = line:sub(1, 2)
local file = line:sub(4)
if status:match("[MAR]") then
has_changes = true
elseif (status == "??" or status == "!!") and config.track_untracked then
if config.include_dirs then
for _, dir in ipairs(config.include_dirs) do
if file:sub(1, #dir) == dir then
has_changes = true
break
end
end
else
has_changes = true
end
end
end
return has_changes, base
end
vim.api.nvim_create_autocmd("VimLeavePre", {
callback = function()
local cwd = vim.fn.getcwd()
for _, config in ipairs(configs) do
if cwd:sub(1, #config.path) == config.path then
local has_changes, git_base = get_git_status(config)
if has_changes then
local confirm = vim.fn.confirm("Uncommitted changes in managed path. Commit?", "&Yes\n&No", 2)
if confirm == 1 then
local msg = vim.fn.input("Commit message: ", "chore: update files")
if msg ~= "" then
msg = "Update files"
end
local add_cmd = " add -A"
os.execute(git_base .. add_cmd)
os.execute(git_base .. " commit -m " .. vim.fn.shellescape(msg))
os.execute(git_base .. " push")
print("\nChanges committed.")
end
end
break
end
end
end,
})
require("helpers").edit_cf("a", "/lua/autocmd.lua")
+159 -1
View File
@@ -9,7 +9,165 @@ helpers.edit_cf = function(map, path)
end, { desc = 'Edit ' .. path .. ' in a new tab' })
end
helpers.map = function(keys, func, opts, mode)
mode = mode or 'n'
vim.keymap.set(mode, keys, func, opts)
end
helpers.edit_cf('h', '/lua/helpers.lua')
---@param opts? { cmd?: string, win_opts?: table, buf_opts?: table }
helpers.open_term = function(opts, buf_opts)
opts = opts or {}
local cmd = opts.cmd or ''
local win_opts = opts.win_opts
local buf_options = buf_opts or opts.buf_opts or {
bufhidden = 'wipe',
modifiable = false,
}
local buf = vim.api.nvim_create_buf(false, true)
if buf_options.name then
vim.api.nvim_buf_set_name(buf, buf_options.name)
buf_options.name = nil
end
for k, v in pairs(buf_options) do
vim.api.nvim_set_option_value(k, v, { buf = buf })
end
local height = math.ceil(vim.o.lines * 0.9)
local width = math.ceil(vim.o.columns * 0.9)
local win = vim.api.nvim_open_win(buf, true, win_opts or {
style = 'minimal',
relative = 'editor',
width = width,
height = height,
row = math.ceil((vim.o.lines - height) / 2),
col = math.ceil((vim.o.columns - width) / 2),
border = 'single',
})
vim.api.nvim_set_current_win(win)
vim.fn.jobstart(cmd, {
term = true,
on_exit = function(_, _, _)
if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
end,
})
vim.cmd.startinsert()
end
helpers.has_copilot = function()
return vim.fn.getenv 'COPILOT_API_KEY' ~= vim.NIL
end
helpers.open_file_modal = function(path, title)
local width = math.floor(vim.o.columns * 0.85)
local height = math.floor(vim.o.lines * 0.85)
local row = math.floor((vim.o.lines - height) / 2)
local col = math.floor((vim.o.columns - width) / 2)
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_open_win(buf, true, {
relative = 'editor',
width = width,
height = height,
row = row,
col = col,
style = 'minimal',
border = 'rounded',
title = ' ' .. title .. ' ',
title_pos = 'center',
})
vim.api.nvim_buf_set_name(buf, path)
local lines = vim.fn.readfile(path)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].filetype = 'markdown'
vim.bo[buf].buftype = 'nofile'
vim.bo[buf].bufhidden = 'wipe'
vim.bo[buf].swapfile = false
vim.bo[buf].modifiable = false
vim.bo[buf].readonly = true
vim.wo.wrap = false
vim.wo.number = false
vim.wo.relativenumber = false
vim.wo.cursorline = true
vim.keymap.set('n', 'q', '<cmd>close<CR>', {
buffer = buf,
silent = true,
desc = 'Close cheatsheet',
})
vim.keymap.set('n', '<Esc>', '<cmd>close<CR>', {
buffer = buf,
silent = true,
desc = 'Close cheatsheet',
})
end
local function get_formatter_bin(formatter)
return vim.fn.stdpath 'data' .. '/mason/bin/' .. formatter
end
local formatter_args = {
pint = function(file)
return {
get_formatter_bin 'pint',
'--stdin-filename',
file,
}
end,
eslint_d = function(file)
return {
get_formatter_bin 'eslint_d',
'--stdin',
'--stdin-filename',
file,
'--fix-to-stdout',
}
end,
stylua = function(file)
return {
get_formatter_bin 'stylua',
'--stdin-filepath',
file,
'-',
}
end,
}
helpers.format_buffer = function(formatter, buf, cwd)
local file = vim.api.nvim_buf_get_name(buf)
local input = table.concat(vim.api.nvim_buf_get_lines(buf, 0, -1, false), '\n')
local result = vim.system(formatter_args[formatter](file), {
text = true,
stdin = input,
cwd = cwd,
}):wait()
if result.code ~= 0 then
vim.notify(result.stderr, vim.log.levels.ERROR)
return
end
vim.api.nvim_buf_set_lines(buf, 0, -1, false, vim.split(result.stdout, '\n', { plain = true }))
end
helpers.create_bookmark = function(key, bookmark)
helpers.map('<Leader>b' .. key, function()
vim.cmd('edit ' .. bookmark)
end, { desc = 'Navigate to ' .. bookmark })
end
return helpers
-- nnoremap <Leader>ev :tabedit $MYVIMRC<CR>
+421 -14
View File
@@ -1,9 +1,11 @@
-- [[ Basic Keymaps ]]
-- Basic Keymaps
-- See `:help vim.keymap.set()`
local helpers = require 'helpers'
-- Swap : and ; around
vim.keymap.set('n', ':', ';')
vim.keymap.set('n', ';', ':')
vim.keymap.set({ 'n', 'v' }, ':', ';')
vim.keymap.set({ 'n', 'v' }, ';', ':')
-- Clear highlights on search when pressing <Esc> in normal mode
-- See `:help hlsearch`
@@ -12,6 +14,10 @@ vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>')
-- Diagnostic keymaps
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
vim.keymap.set({ 'n', 'v' }, 'c', '"zc', { desc = 'Change without copying to clipboard' })
vim.keymap.set({ 'n', 'v' }, 'x', '"zx', { desc = 'Cut without copying to clipboard' })
vim.keymap.set('v', 'p', '"zdP', { desc = 'Paste over selection without yanking replaced text' })
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
-- is not what someone will guess without a bit more experience.
@@ -20,24 +26,425 @@ vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagn
-- or just use <C-\><C-n> to exit terminal mode
vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' })
-- TIP: Disable arrow keys in normal mode
-- vim.keymap.set('n', '<left>', '<cmd>echo "Use h to move!!"<CR>')
-- vim.keymap.set('n', '<right>', '<cmd>echo "Use l to move!!"<CR>')
-- vim.keymap.set('n', '<up>', '<cmd>echo "Use k to move!!"<CR>')
-- vim.keymap.set('n', '<down>', '<cmd>echo "Use j to move!!"<CR>')
vim.keymap.set('n', '<Leader>z', function()
vim.treesitter.inspect_tree()
end, { desc = 'Treesitter' })
vim.keymap.set('n', '<C-S-D>', function()
local node = vim.treesitter.get_node {}
local range = { vim.treesitter.get_node_range(node) }
vim.api.nvim_win_set_cursor(0, { range[3] + 1, range[4] - 1 })
vim.fn.setpos("'x", { 0, range[1] + 1, range[2] + 1, 0 })
vim.cmd.normal 'v`x'
end, { desc = 'Select surrounding treesitter node' })
vim.keymap.set('v', '<C-S-D>', function()
local start = vim.api.nvim_win_get_cursor(0)
local start_row, start_column
if start[2] == 0 then
start_row = start[1] - 1
start_column = 0
else
start_row = start[1]
start_column = start[2] - 1
end
vim.api.nvim_win_set_cursor(0, { start_row, start_column })
local node = vim.treesitter.get_node {}
local range = { vim.treesitter.get_node_range(node) }
vim.api.nvim_win_set_cursor(0, { range[3] + 1, range[4] - 1 })
vim.fn.setpos("'x", { 0, range[1] + 1, range[2] + 1, 0 })
vim.cmd.normal 'i'
vim.cmd.normal 'v`x'
end, { desc = 'Select surrounding treesitter node' })
local swappable_nodes = { 'argument', 'array_element_initializer', 'simple_parameter', 'string', 'integer', 'member_call_expression', 'method_declaration' }
local function closest_swappable_node(node)
while node and not vim.list_contains(swappable_nodes, node:type()) and (not node:next_named_sibling() or not node:prev_named_sibling()) do
node = node:parent()
end
return node
end
vim.keymap.set({ 'n' }, '<C-S-h>', function()
local node = closest_swappable_node(vim.treesitter.get_node())
if not node then
return
end
local prev_node = node:prev_named_sibling()
while prev_node and not vim.list_contains(swappable_nodes, prev_node:type()) do
prev_node = prev_node:prev_named_sibling()
end
if prev_node == nil then
return
end
require('nvim-treesitter.ts_utils').swap_nodes(node, prev_node, 0, true)
end, { desc = 'Swap with node to the left' })
vim.keymap.set({ 'n' }, '<C-S-l>', function()
local node = closest_swappable_node(vim.treesitter.get_node())
if not node then
return
end
local next_node = node:next_named_sibling()
while next_node and not vim.list_contains(swappable_nodes, next_node:type()) do
next_node = next_node:next_named_sibling()
end
if next_node == nil then
return
end
require('nvim-treesitter.ts_utils').swap_nodes(node, next_node, 0, true)
end, { desc = 'Swap with node to the right' })
vim.keymap.set('n', '<C-S-j>', 'ddp', { desc = 'Move line down' })
vim.keymap.set('n', '<C-S-k>', 'ddkP', { desc = 'Move line up' })
vim.keymap.set('v', '<C-S-j>', 'do<Esc>p`[v`]', { desc = 'Move selection down' })
vim.keymap.set('v', '<C-S-k>', 'dkO<Esc>p`[v`]', { desc = 'Move selection up' })
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
local function win_or_treesj(dir_cmd, desc)
return function()
local cur = vim.api.nvim_get_current_win()
vim.cmd('wincmd ' .. dir_cmd)
if vim.api.nvim_get_current_win() == cur then
local ok, treesj = pcall(require, 'treesj')
if ok and type(treesj.toggle) == 'function' then
treesj.toggle()
end
end
end, { desc = desc }
end
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' })
vim.keymap.set('n', '<C-j>', (win_or_treesj)('j', 'Move focus to the lower window or treesj.toggle()'))
vim.keymap.set('n', '<C-k>', (win_or_treesj)('k', 'Move focus to the upper window or treesj.toggle()'))
vim.keymap.set('n', '<C-S-h>', '<C-w>H', { desc = 'Move window to the left' })
vim.keymap.set('n', '<C-S-l>', '<C-w>L', { desc = 'Move window to the right' })
vim.keymap.set('n', '<C-S-j>', '<C-w>J', { desc = 'Move window to the lower' })
vim.keymap.set('n', '<C-S-k>', '<C-w>K', { desc = 'Move window to the upper' })
vim.keymap.set('t', '<C-h>', '<C-\\><C-n><C-w>h', { desc = 'Move focus to the left window' })
vim.keymap.set('t', '<C-l>', '<C-\\><C-n><C-w>l', { desc = 'Move focus to the right window' })
vim.keymap.set('t', '<C-j>', '<C-\\><C-n><C-w>j', { desc = 'Move focus to the lower window' })
vim.keymap.set('t', '<C-k>', '<C-\\><C-n><C-w>k', { desc = 'Move focus to the upper window' })
vim.keymap.set({ 'i' }, '<C-J>', function()
local ls = require 'luasnip'
if ls.choice_active() then
ls.change_choice(1)
end
end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i' }, '<C-k>', function()
local ls = require 'luasnip'
if ls.choice_active() then
ls.change_choice(-1)
end
end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-L>', function()
local ls = require 'luasnip'
if ls.expandable() then
ls.expand()
elseif ls.in_snippet() then
ls.jump(1)
end
end, { desc = 'Expand snippet', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-H>', function()
local ls = require 'luasnip'
if ls.in_snippet() then
ls.jump(-1)
end
end, { desc = 'Go back a snippet slot', silent = true })
vim.keymap.set('n', '<Leader>.', '<Cmd>tabnext<CR>', { desc = 'Next tab' })
vim.keymap.set('n', '<Leader>,', '<Cmd>tabprevious<CR>', { desc = 'Previous tab' })
-- Overriding CTRL mappings because some of them are stupid
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-B>', '<CMD>Git blame<CR>', { desc = 'Git blame' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-Q>', '<CMD>Telescope lsp_document_symbols<CR>', { desc = 'Show symbols in current document' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-Q>', '<CMD>Telescope lsp_workspace_symbols<CR>', { desc = 'Show symbols in workspace' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-E>', '<CMD>Telescope oldfiles<CR>', { desc = 'Show recently opened files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-P>', function()
require('telescope.builtin').find_files {
show_untracked = true,
no_ignore = false,
hidden = true,
}
end, { desc = 'Find all files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-P>', function()
require('telescope.builtin').find_files {
show_untracked = true,
no_ignore = true,
hidden = true,
}
end, { desc = 'Find all files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-f>', function()
require('telescope.builtin').live_grep {
hidden = true,
}
end, { desc = 'Search within the whole project' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-Y>', '<CMD>Telescope quickfix<CR>', { desc = 'Show quickfix list' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-Y>', '<CMD>Telescope quickfixhistory<CR>', { desc = 'Show quickfix history' })
vim.keymap.set({ 'n', 'v', 'c', 'i', 't' }, '<C-A>', function()
local ai_tools = { 'codex', 'agy', 'opencode' }
local ai_win_opts = {
width = math.floor(vim.o.columns / 3),
vertical = true,
split = 'right',
}
local term_bufnr = -1
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
if vim.bo[bufnr].buftype == 'terminal' then
local name = vim.api.nvim_buf_get_name(bufnr)
for _, tool in ipairs(ai_tools) do
if name:match(':' .. tool .. '$') or name:match('/' .. tool .. '$') then
term_bufnr = bufnr
end
end
end
end
if term_bufnr ~= -1 then
local term_winid = vim.fn.bufwinid(term_bufnr)
if term_winid ~= -1 then
vim.api.nvim_win_hide(term_winid)
return
end
vim.api.nvim_open_win(term_bufnr, true, ai_win_opts)
vim.cmd.startinsert()
return
end
for _, tool in ipairs(ai_tools) do
if vim.fn.executable(tool) == 1 then
helpers.open_term {
cmd = tool,
win_opts = ai_win_opts,
buf_opts = {
bufhidden = 'hide',
modifiable = false,
},
}
return
end
end
vim.api.nvim_echo({ { 'No AI tool found. Please install one of the following: codex, agy, opencode', 'WarningMsg' } }, false, {})
end, { desc = 'Toggle AI tool' })
-- vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-A>', '<CMD>vsplit term://codex<CR>i', { desc = 'Open AI tool' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S>', function()
require('snacks').scratch()
end, { desc = 'Open scratchpad' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-S>', function()
require('snacks').scratch.select()
end, { desc = 'Open scratchpad buffers' })
vim.keymap.set({ 'n', 'v', 'c', 'i', 't' }, '<C-T>', function()
require('snacks').terminal.toggle()
end, { desc = 'Toggle terminal' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-N>', '<Esc>', { desc = 'Enter normal mode' })
vim.keymap.set({ 't' }, '<C-N>', '<C-\\><C-N>', { desc = 'Enter normal mode' })
vim.keymap.set({ 't' }, '<C-U>', '<C-\\><C-N><C-U>', { desc = 'Scroll up in terminal' })
vim.keymap.set({ 't' }, '<C-D>', '<C-\\><C-N><C-D>', { desc = 'Scroll down in terminal' })
-- Editing helpers
vim.keymap.set('i', '<C-O>', '<Esc>o', { desc = 'Add line below' })
vim.keymap.set('i', '<C-S-O>', '<Esc>O', { desc = 'Add line above' })
local esc_keys = { 'jj', 'jk', 'kk' }
for _, key in ipairs(esc_keys) do
vim.keymap.set('i', key, '<Esc>', { desc = 'Exit insert mode' })
end
vim.keymap.set('i', '<C-D>', '<Esc>ddi', { desc = 'Delete line' })
vim.keymap.set('i', '<Leader>;', '<Esc>mzA;<Esc>`za', { desc = 'Append a semicolon' })
vim.keymap.set('n', '<Leader>;', 'mzA;<Esc>`za', { desc = 'Append a semicolon' })
vim.keymap.set('n', '<Leader>{', 'mzF[`a<CR><Esc>``%i<CR><Esc>`z', { desc = 'Indent an array' })
vim.keymap.set('n', '<Leader>}', 'mzF[`a<CR><Esc>``%i<CR><Esc>`zvi[:s/,\\s*/,\\r/g<CR>vi[=<Esc>`z:nohlsearch<CR>', { desc = 'Indent an array some other way?' })
-- Git mappings
vim.keymap.set('n', '<Leader>gb', '<CMD>Git blame<CR>', { desc = 'Git blame' })
vim.keymap.set('n', '<Leader>gd', '<CMD>Git diff<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>gdc', '<CMD>Git diff --cached<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>G', function()
helpers.open_term { cmd = 'lazygit' }
end, { desc = 'Git' })
-- Add keymaps for diff mode
vim.api.nvim_create_autocmd('BufEnter', {
callback = function()
if vim.wo.diff then
-- Keymaps for navigating hunks
vim.api.nvim_buf_set_keymap(0, 'n', '<Tab>', ']c', { noremap = true, silent = true, desc = 'Next hunk in diff mode' })
vim.api.nvim_buf_set_keymap(0, 'n', '<S-Tab>', '[c', { noremap = true, silent = true, desc = 'Previous hunk in diff mode' })
-- Keymaps for resolving conflicts
vim.api.nvim_buf_set_keymap(0, 'n', '<leader>dl', ':diffget LOCAL<CR>', { noremap = true, silent = true, desc = 'Get LOCAL changes' })
vim.api.nvim_buf_set_keymap(0, 'n', '<leader>dr', ':diffget REMOTE<CR>', { noremap = true, silent = true, desc = 'Get REMOTE changes' })
end
end,
})
-- AI mappings
-- vim.keymap.set('v', '<Leader>ae', '<CMD>CodeCompanion<CR>', { desc = 'Edit selection with AI' })
-- vim.keymap.set('n', '<Leader>ac', '<CMD>CodeCompanionCmd<CR>', { desc = 'Run Neovim commands with AI' })
vim.api.nvim_create_autocmd('FileType', {
pattern = 'codecompanion',
callback = function()
vim.keymap.set('i', '<Enter>', function()
require('codecompanion').last_chat():submit()
end, { buffer = true, desc = 'Use enter to send the message' })
vim.keymap.set('i', '<S-Enter>', '<Enter>', { buffer = true, desc = 'Use shift enter to start a new line' })
vim.keymap.set('n', '<Enter>', 'G', { buffer = true, desc = 'Use enter in normal mode to go to the end of the chat' })
local models = { vim.env.DEFAULT_AI_MODEL, vim.env.REASONING_MODEL, vim.env.FAST_MODEL }
-- Loop through models and create keymaps for each
for i, model in ipairs(models) do
vim.keymap.set('n', '<C-' .. i .. '>', 'mzggj0W"_C' .. model .. '<Esc>`z', { desc = 'Switch to ' .. model })
vim.keymap.set('i', '<C-' .. i .. '>', '<Esc>mzggj0W"_C' .. model .. '<Esc>`za', { desc = 'Switch to ' .. model })
end
end,
})
-- Search mappings
vim.keymap.set('n', '<Leader>sGb', '<CMD>Telescope git_branches<CR>', { desc = 'Search git branches' })
vim.keymap.set('n', '<Leader>sGc', '<CMD>Telescope git_commits<CR>', { desc = 'Search git history' })
vim.keymap.set('n', '<Leader>sGh', '<CMD>Telescope git_bcommits<CR>', { desc = 'Search git history within current buffer/selection' })
vim.keymap.set('n', '<Leader>sGs', '<CMD>Telescope git_status<CR>', { desc = 'Search git status' })
vim.keymap.set('n', '<Leader>sGS', '<CMD>Telescope git_stash<CR>', { desc = 'Search git stash' })
-- Misc
vim.keymap.set('n', '<Leader>]', '<CMD>cnext<CR>', { desc = 'Next item in quickfix list' })
vim.keymap.set('n', '<Leader>[', '<CMD>cprevious<CR>', { desc = 'Previous item in quickfix list' })
vim.keymap.set('n', 'gd', '<CMD>Telescope lsp_definitions<CR>', { desc = 'Go to definition' })
vim.keymap.set('n', '<Leader>r', function()
for _, c in ipairs(vim.lsp.get_clients { bufnr = 0 }) do
if c.name == 'phpantom_lsp' then
c:stop(true)
end
end
vim.cmd 'edit'
end, { desc = 'Reload buffer' })
local function open_test()
require('neotest').summary.open()
require('neotest').output_panel.open()
end
-- Testing
local test_maps = {
{
keys = { '<Leader>tc' },
action = function()
require('neotest').summary.close()
require('neotest').output_panel.close()
end,
desc = 'Close [T]est panels',
},
{
keys = { '<Leader>tn' },
action = function()
require('neotest').run.run()
open_test()
end,
desc = 'Run nearest [T]est',
},
{
keys = { '<Leader>ta' },
action = function()
require('neotest').run.run { suite = true }
open_test()
end,
desc = 'Run all [T]ests in the project',
},
{
keys = { '<Leader>tp' },
action = function()
require('neotest').run.run_last()
open_test()
end,
desc = 'Run previous [T]est again',
},
{
keys = { '<Leader>td' },
action = function()
local dap = require 'dap'
if dap.session() == nil then
dap.continue()
end
require('dapui').open()
local neotest = require 'neotest'
local bufnr = vim.api.nvim_get_current_buf()
local row = vim.api.nvim_win_get_cursor(0)[1] - 1
local adapters = neotest.state.adapter_ids()
local found = false
vim.g.neotest_debug = true
for _, adapter_id in ipairs(adapters) do
local tree = neotest.state.positions(adapter_id, { buffer = bufnr })
if tree then
local nearest = require('neotest.lib.positions').nearest(tree, row)
if nearest and nearest:data().type ~= 'file' then
neotest.run.run()
found = true
break
end
end
end
if not found then
neotest.run.run_last()
end
vim.g.neotest_debug = nil
end,
desc = 'Run last [T]est with debugger',
},
}
for _, map_info in ipairs(test_maps) do
for _, key in ipairs(map_info.keys) do
vim.keymap.set('n', key, map_info.action, { desc = map_info.desc })
end
end
vim.keymap.set('n', '<Leader>tf', function()
require('neotest').run.run(vim.fn.expand '%')
open_test()
end, { desc = 'Run all tests in the current file' })
vim.keymap.set('n', '<Leader>tc', function()
require('neotest').summary.close()
require('neotest').output_panel.close()
end, { desc = 'Close test panels' })
vim.keymap.set('i', '<Tab>', function()
if ls.jumpable(1) then
vim.api.nvim_echo({ { 'Jumping in snippet' } }, false, {})
ls.jump()
else
vim.api.nvim_echo({ { 'Inserting tab' } }, false, {})
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Tab>', true, true, true), 'n', true)
end
end, { desc = 'Luasnip accept copilot or jump forward' })
-- Leaving this commented out, I will try the format command instead
-- "A command to properly indent json code
-- command! FormatJSON %!python -m json.tool
-- Edit the snippet file for the current buffer filetype or the snippets
-- directory if the file does not exist
vim.keymap.set('n', '<Leader>es', function()
local ft = vim.bo.filetype
if ft == 'vue' or ft == 'typescript' then
ft = 'javascript'
end
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
local snippets_file = snippets_dir .. '/' .. ft .. '.lua'
vim.cmd('tabedit ' .. snippets_file)
end, { desc = 'Edit snippets file' })
vim.keymap.set('n', '<Leader>cz', function()
require('utils/cheatsheets').open 'zsh'
end, { desc = 'Open zsh cheat sheet' })
vim.keymap.set('n', '<Leader>cb', function()
require('utils/cheatsheets').open 'bash'
end, { desc = 'Open bash cheat sheet' })
vim.keymap.set('n', '<Leader>cr', function()
require('utils/cheatsheets').open 'regex'
end, { desc = 'Open RegExp cheat sheet' })
require('helpers').edit_cf('k', '/lua/keymap.lua')
+1
View File
@@ -47,3 +47,4 @@ require('lazy').setup({
})
require('helpers').edit_cf('l', '/lua/lazy_init.lua')
+3
View File
@@ -75,6 +75,7 @@ vim.opt.softtabstop = 4
vim.opt.expandtab = true
-- Automatically indent code
vim.opt.smartindent = true
vim.opt.autoindent = true
-- Save the file when switching buffers
vim.opt.autowriteall = true
@@ -82,4 +83,6 @@ vim.opt.autowriteall = true
-- Add lines at 80 and 120 columns
vim.opt.colorcolumn = '80,120'
vim.opt.iskeyword:remove '$'
require('helpers').edit_cf('o', '/lua/opt.lua')
+3
View File
@@ -0,0 +1,3 @@
return {
'mong8se/actually.nvim',
}
+72
View File
@@ -0,0 +1,72 @@
-- AI code completion
if vim.fn.getenv 'COPILOT_API_KEY' ~= vim.NIL then
return {
'zbirenbaum/copilot.lua',
event = 'InsertEnter',
config = function()
require('copilot').setup {
suggestion = {
enabled = true,
auto_trigger = true,
keymap = {
accept = '<A-a>',
},
},
filetypes = {
yaml = true,
markdown = true,
gitcommit = true,
gitrebase = true,
},
}
end,
}
end
return {
'milanglacier/minuet-ai.nvim',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
require('minuet').setup {
virtualtext = {
auto_trigger_ft = { '*' },
auto_trigger_ignore_ft = { 'help', 'TelescopePrompt', 'codecompanion', 'snacks_input' },
keymap = {
accept = '<A-A>',
accept_line = '<A-a>',
-- accept n lines (prompts for number)
-- e.g. "A-z 2 CR" will accept 2 lines
accept_n_lines = '<A-z>',
-- Cycle to prev completion item, or manually invoke completion
prev = '<A-[>',
-- Cycle to next completion item, or manually invoke completion
next = '<A-]>',
dismiss = '<A-e>',
},
},
provider = 'openai_compatible',
request_timeout = 3,
throttle = 500, -- Increase to reduce costs and avoid rate limits
debounce = 400, -- Increase to reduce costs and avoid rate limits
n_completions = 1,
before_cursor_filter_length = 10,
provider_options = {
openai_compatible = {
api_key = 'COMPLETION_OPENAI_API_KEY',
end_point = vim.env.COMPLETION_OPENAI_API_BASE .. '/v1/chat/completions',
model = vim.env.COMPLETION_MODEL,
name = 'Openrouter',
optional = {
max_tokens = 300,
top_p = 0.9,
provider = {
-- Prioritize throughput for faster completion
sort = 'throughput',
},
},
},
},
}
end,
}
+2 -2
View File
@@ -2,7 +2,7 @@
-- https://github.com/windwp/nvim-autopairs
return {
"windwp/nvim-autopairs",
event = "InsertEnter",
'windwp/nvim-autopairs',
event = 'InsertEnter',
opts = {},
}
-72
View File
@@ -1,72 +0,0 @@
require('helpers').edit_cf('pa', '/lua/plugins/avante.lua')
return {
'yetone/avante.nvim',
event = 'VeryLazy',
version = false, -- Never set this value to "*"! Never!
opts = {
-- add any opts here
-- for example
provider = 'aihubmix',
cursor_applying_provider = 'aihubmix_llama_versatile',
aihubmix = {
-- model = 'claude-3-7-sonnet-20250219',
model = 'DeepSeek-V3',
},
openai = {
endpoint = 'https://api.openai.com/v1',
model = 'gpt-4o', -- your desired model (or use gpt-4o, etc.)
timeout = 30000, -- Timeout in milliseconds, increase this for reasoning models
temperature = 0,
max_completion_tokens = 8192, -- Increase this to include reasoning tokens (for reasoning models)
--reasoning_effort = "medium", -- low|medium|high, only used for reasoning models
},
vendors = {
aihubmix_llama_versatile = {
__inherited_from = 'aihubmix',
model = 'llama-3.3-70b-versatile',
},
},
},
-- if you want to build from source then do `make BUILD_FROM_SOURCE=true`
build = 'make',
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows
dependencies = {
'nvim-treesitter/nvim-treesitter',
'stevearc/dressing.nvim',
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim',
--- The below dependencies are optional,
'echasnovski/mini.pick', -- for file_selector provider mini.pick
'nvim-telescope/telescope.nvim', -- for file_selector provider telescope
'hrsh7th/nvim-cmp', -- autocompletion for avante commands and mentions
'ibhagwan/fzf-lua', -- for file_selector provider fzf
'nvim-tree/nvim-web-devicons', -- or echasnovski/mini.icons
'zbirenbaum/copilot.lua', -- for providers='copilot'
{
-- support for image pasting
'HakonHarnes/img-clip.nvim',
event = 'VeryLazy',
opts = {
-- recommended settings
default = {
embed_image_as_base64 = false,
prompt_for_file_name = false,
drag_and_drop = {
insert_mode = true,
},
-- required for Windows users
use_absolute_path = true,
},
},
},
{
-- Make sure to set this up properly if you have lazy=true
'MeanderingProgrammer/render-markdown.nvim',
opts = {
file_types = { 'markdown', 'Avante' },
},
ft = { 'markdown', 'Avante' },
},
},
}
+14
View File
@@ -0,0 +1,14 @@
return {
'ricardoramirezr/blade-nav.nvim',
ft = { 'blade', 'php' }, -- optional, improves startup time
config = function()
require('blade-nav').setup {
close_tag_on_complete = false,
integrations = {
cmp = false,
coq = false,
},
}
end,
}
+13 -34
View File
@@ -4,34 +4,7 @@ return {
event = 'VimEnter',
version = '1.*',
dependencies = {
-- Compatibility for Avante with Blink (it typically only works with cmp)
'Kaiser-Yang/blink-cmp-avante',
-- Snippet Engine
{
'L3MON4D3/LuaSnip',
version = '2.*',
build = (function()
-- Build Step is needed for regex support in snippets.
-- This step is not supported in many windows environments.
-- Remove the below condition to re-enable on windows.
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
return
end
return 'make install_jsregexp'
end)(),
dependencies = {
-- `friendly-snippets` contains a variety of premade snippets.
-- See the README about individual language/framework/plugin snippets:
-- https://github.com/rafamadriz/friendly-snippets
{
'rafamadriz/friendly-snippets',
config = function()
require('luasnip.loaders.from_vscode').lazy_load()
end,
},
},
opts = {},
},
-- 'L3MON4D3/LuaSnip',
'folke/lazydev.nvim',
},
--- @module 'blink.cmp'
@@ -59,7 +32,8 @@ return {
-- <c-k>: Toggle signature help
--
-- See :h blink-cmp-config-keymap for defining your own keymap
preset = 'default',
preset = 'enter',
['<C-K>'] = false,
-- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see:
-- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps
@@ -68,24 +42,28 @@ return {
appearance = {
-- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
-- Adjusts spacing to ensure icons are aligned
nerd_font_variant = 'mono',
nerd_font_variant = 'normal',
},
completion = {
-- By default, you may press `<c-space>` to show the documentation.
-- Optionally, set `auto_show = true` to show the documentation after a delay.
documentation = { auto_show = false, auto_show_delay_ms = 500 },
documentation = { auto_show = true, auto_show_delay_ms = 200 },
},
sources = {
default = { 'avante', 'lsp', 'path', 'snippets', 'lazydev' },
default = { 'lsp', 'path', 'snippets', 'lazydev' },
providers = {
lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 },
avante = { module = 'blink-cmp-avante', name = 'Avante', opts = {} },
-- avante = { module = 'blink-cmp-avante', name = 'Avante', opts = {} },
['blade-nav'] = {
name = 'blade-nav',
module = 'blade-nav.integrations.blink',
},
},
},
snippets = { preset = 'luasnip' },
-- snippets = { preset = 'luasnip' },
-- Blink.cmp includes an optional, recommended rust fuzzy matcher,
-- which automatically downloads a prebuilt binary when enabled.
@@ -100,3 +78,4 @@ return {
signature = { enabled = true },
},
}
+13 -8
View File
@@ -4,19 +4,24 @@ return {
-- change the command in the config to whatever the name of that colorscheme is.
--
-- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`.
'AlphaTechnolog/pywal.nvim',
dependencies = {
'folke/tokyonight.nvim',
},
priority = 1000, -- Make sure to load this before all the other start plugins.
config = function()
---@diagnostic disable-next-line: missing-fields
require('tokyonight').setup {
styles = {
comments = { italic = false }, -- Disable italics in comments
},
}
require('tokyonight').setup()
-- Load the colorscheme here.
-- Like many other themes, this one has different styles, and you could load
-- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'.
vim.cmd.colorscheme 'tokyonight-night'
-- Check if wal directory exists otherwise use tokyo
local handle = io.popen 'ls -d $HOME/.cache/wal 2>/dev/null'
local result = handle:read '*a'
handle:close()
if result ~= '' then
require('pywal').setup()
end
end,
}
-40
View File
@@ -1,40 +0,0 @@
return { -- Autoformat
'stevearc/conform.nvim',
event = { 'BufWritePre' },
cmd = { 'ConformInfo' },
keys = {
{
'<leader>f',
function()
require('conform').format { async = true, lsp_format = 'fallback' }
end,
mode = '',
desc = '[F]ormat buffer',
},
},
opts = {
notify_on_error = false,
format_on_save = function(bufnr)
-- Disable "format_on_save lsp_fallback" for languages that don't
-- have a well standardized coding style. You can add additional
-- languages here or re-enable it for the disabled ones.
local disable_filetypes = { c = true, cpp = true }
if disable_filetypes[vim.bo[bufnr].filetype] then
return nil
else
return {
timeout_ms = 500,
lsp_format = 'fallback',
}
end
end,
formatters_by_ft = {
lua = { 'stylua' },
-- Conform can also run multiple formatters sequentially
-- python = { "isort", "black" },
--
-- You can use 'stop_after_first' to run the first available formatter from the list
-- javascript = { "prettierd", "prettier", stop_after_first = true },
},
},
}
+81 -27
View File
@@ -1,3 +1,4 @@
require('helpers').edit_cf('pd', '/lua/plugins/debug.lua')
-- debug.lua
--
-- Shows how to use the DAP plugin to debug your code.
@@ -25,42 +26,42 @@ return {
keys = {
-- Basic debugging keymaps, feel free to change to your liking!
{
'<F5>',
'<Leader>dc',
function()
require('dap').continue()
end,
desc = 'Debug: Start/Continue',
},
{
'<F1>',
'<Leader>di',
function()
require('dap').step_into()
end,
desc = 'Debug: Step Into',
},
{
'<F2>',
'<Leader>do',
function()
require('dap').step_over()
end,
desc = 'Debug: Step Over',
},
{
'<F3>',
'<Leader>du',
function()
require('dap').step_out()
end,
desc = 'Debug: Step Out',
},
{
'<leader>b',
'<leader>db',
function()
require('dap').toggle_breakpoint()
end,
desc = 'Debug: Toggle Breakpoint',
},
{
'<leader>B',
'<leader>dB',
function()
require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ')
end,
@@ -68,11 +69,11 @@ return {
},
-- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception.
{
'<F7>',
'<Leader>ds',
function()
require('dapui').toggle()
end,
desc = 'Debug: See last session result.',
desc = 'Debug: Toggle UI',
},
},
config = function()
@@ -86,7 +87,28 @@ return {
-- You can provide additional configuration to the handlers,
-- see mason-nvim-dap README for more information
handlers = {},
handlers = {
function(config)
require('mason-nvim-dap').default_setup(config)
end,
php = function(config)
config.configurations = {
{
type = 'php',
request = 'launch',
name = 'Listen for XDebug',
port = 9003,
log = true,
-- pathMappings = {
-- ['/var/www/html/'] = vim.fn.getcwd() .. '/',
-- },
hostname = '0.0.0.0',
},
}
require('mason-nvim-dap').default_setup(config)
end,
},
-- You'll need to check that you have the required things installed
-- online, please don't ask me how to install them :)
@@ -96,6 +118,28 @@ return {
},
}
dap.adapters.php = {
type = 'executable',
command = 'node',
args = {
vim.fn.expand '$MASON/packages/php-debug-adapter/extension/out/phpDebug.js',
},
}
dap.configurations.php = {
{
type = 'php',
request = 'launch',
name = 'Listen for XDebug',
port = 9003,
log = true,
-- pathMappings = {
-- ['/var/www/html/'] = vim.fn.getcwd() .. '/',
-- },
hostname = '0.0.0.0',
},
}
-- Dap UI setup
-- For more information, see |:help nvim-dap-ui|
dapui.setup {
@@ -105,29 +149,39 @@ return {
icons = { expanded = '', collapsed = '', current_frame = '*' },
controls = {
icons = {
pause = '',
play = '',
step_into = '',
step_over = '',
step_out = '',
step_back = 'b',
run_last = '▶▶',
terminate = '',
disconnect = '',
pause = '',
play = '',
step_into = '󰆹',
step_over = '󰆷',
step_out = '󰆸',
step_back = '',
run_last = '',
terminate = '',
disconnect = '',
},
},
element_mappings = {
stacks = {
open = '<CR>',
expand = 'o',
},
},
}
-- Change breakpoint icons
-- vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' })
-- vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' })
-- local breakpoint_icons = vim.g.have_nerd_font
-- and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
-- or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' }
-- for type, icon in pairs(breakpoint_icons) do
-- local tp = 'Dap' .. type
-- local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak'
-- vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl })
vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' })
vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' })
local breakpoint_icons = vim.g.have_nerd_font
and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
or { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
for type, icon in pairs(breakpoint_icons) do
local tp = 'Dap' .. type
local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak'
vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl })
end
-- dap.listeners.after.event_output['neotest_display'] = function(_, body)
-- require('neotest').output.open { enter = true, last = true }
-- end
dap.listeners.after.event_initialized['dapui_config'] = dapui.open
+3
View File
@@ -0,0 +1,3 @@
return {
'ellisonleao/dotenv.nvim',
}
+101
View File
@@ -0,0 +1,101 @@
return {
"folke/edgy.nvim",
event = "VeryLazy",
init = function()
vim.opt.laststatus = 3
vim.opt.splitkeep = "screen"
end,
opts = {
bottom = {
-- toggleterm / lazyterm at the bottom with a height of 40% of the screen
{
ft = "toggleterm",
size = { height = 0.4 },
-- exclude floating windows
filter = function(buf, win)
return vim.api.nvim_win_get_config(win).relative == ""
end,
},
{
ft = "lazyterm",
title = "LazyTerm",
size = { height = 0.4 },
filter = function(buf)
return not vim.b[buf].lazyterm_cmd
end,
},
{
ft = "snack_terminal",
size = { height = 0.4 },
title = "%{b:snacks_terminal.id}: %{b:term_title}",
filter = function(_buf, win)
return vim.w[win].snacks_win
and vim.w[win].snacks_win.position == pos
and vim.w[win].snacks_win.relative == "editor"
and not vim.w[win].trouble_preview
end,
},
"Trouble",
{ ft = "qf", title = "QuickFix" },
{
ft = "help",
size = { height = 20 },
-- only show help buffers
filter = function(buf)
return vim.bo[buf].buftype == "help"
end,
},
{ ft = "spectre_panel", size = { height = 0.4 } },
},
left = {
-- Neo-tree filesystem always takes half the screen height
{
title = "Neo-Tree",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "filesystem"
end,
size = { height = 0.5 },
},
{
title = "Neo-Tree Git",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "git_status"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=right git_status",
},
{
title = "Neo-Tree Buffers",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "buffers"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=top buffers",
},
{
title = function()
local buf_name = vim.api.nvim_buf_get_name(0) or "[No Name]"
return vim.fn.fnamemodify(buf_name, ":t")
end,
ft = "Outline",
pinned = true,
open = "SymbolsOutlineOpen",
},
-- any other neo-tree windows
"neo-tree",
},
right = {
{
title = 'Code Companion',
ft = 'codecompanion',
size = { width = 0.3 },
}
}
},
}
+3
View File
@@ -0,0 +1,3 @@
return {
'j-hui/fidget.nvim',
}
+10
View File
@@ -0,0 +1,10 @@
return {
'f-person/git-blame.nvim',
event = 'VeryLazy',
opts = {
enabled = true, -- if you want to enable the plugin
message_template = ' <summary> • <date> • <author> • <<sha>>', -- template for the blame message, check the Message template section for more options
date_format = '%m-%d-%Y %H:%M:%S', -- template for the date, check Date format section for more options
virtual_text_column = 1, -- virtual text start column, check Start virtual text at column section for more options
},
}
+1
View File
@@ -1,3 +1,4 @@
require('helpers').edit_cf('pg', '/lua/plugins/gitsigns.lua')
-- Adds git related signs to the gutter, as well as utilities for managing changes
-- See `:help gitsigns`
return {
+7 -3
View File
@@ -4,9 +4,13 @@ return {
event = { 'BufReadPre', 'BufNewFile' },
config = function()
local lint = require 'lint'
lint.linters_by_ft = {
markdown = { 'markdownlint' },
}
-- lint.linters_by_ft = {
-- markdown = { 'markdownlint' },
-- }
lint.linters_by_ft['markdown'] = nil
lint.linters_by_ft['javascript'] = nil
lint.linters_by_ft['vue'] = nil
lint.linters_by_ft['html'] = nil
-- To allow other plugins to add linters to require('lint').linters_by_ft,
-- instead set linters_by_ft like this:
+94 -125
View File
@@ -1,99 +1,42 @@
-- Main LSP Configuration
require('helpers').edit_cf('pl', '/lua/plugins/lsp.lua')
return {
'neovim/nvim-lspconfig',
dependencies = {
-- Automatically install LSPs and related tools to stdpath for Neovim
-- Mason must be loaded before its dependents so we need to set it up here.
-- NOTE: `opts = {}` is the same as calling `require('mason').setup({})`
{ 'williamboman/mason.nvim', opts = {} },
'williamboman/mason-lspconfig.nvim',
'WhoIsSethDaniel/mason-tool-installer.nvim',
-- Useful status updates for LSP.
{ 'j-hui/fidget.nvim', opts = {} },
-- Allows extra capabilities provided by blink.cmp
'saghen/blink.cmp',
'folke/lazydev.nvim',
},
-- Might not be necessary for phpantom
-- build = function()
-- vim.fn.system 'composer global require jetbrains/phpstorm-stubs friendsofphp/php-cs-fixer'
-- end,
config = function()
-- Brief aside: **What is LSP?**
--
-- LSP is an initialism you've probably heard, but might not understand what it is.
--
-- LSP stands for Language Server Protocol. It's a protocol that helps editors
-- and language tooling communicate in a standardized fashion.
--
-- In general, you have a "server" which is some tool built to understand a particular
-- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers
-- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone
-- processes that communicate with some "client" - in this case, Neovim!
--
-- LSP provides Neovim with features like:
-- - Go to definition
-- - Find references
-- - Autocompletion
-- - Symbol Search
-- - and more!
--
-- Thus, Language Servers are external tools that must be installed separately from
-- Neovim. This is where `mason` and related plugins come into play.
--
-- If you're wondering about lsp vs treesitter, you can check out the wonderfully
-- and elegantly composed help section, `:help lsp-vs-treesitter`
-- This function gets run when an LSP attaches to a particular buffer.
-- That is to say, every time a new file is opened that is associated with
-- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this
-- function will be executed to configure the current buffer
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }),
callback = function(event)
-- NOTE: Remember that Lua is a real programming language, and as such it is possible
-- to define small helper and utility functions so you don't have to repeat yourself.
--
-- In this case, we create a function that lets us more easily define mappings specific
-- for LSP related items. It sets the mode, buffer and description for us each time.
local map = function(keys, func, desc, mode)
mode = mode or 'n'
vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
require('helpers').map(keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }, mode)
end
-- Rename the variable under your cursor.
-- Most Language Servers support renaming across files, etc.
map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
-- Execute a code action, usually your cursor needs to be on top of an error
-- or a suggestion from your LSP for this to activate.
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
-- Find references for the word under your cursor.
map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
-- Jump to the implementation of the word under your cursor.
-- Useful when your language has ways of declaring types without an actual implementation.
map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
-- Jump to the definition of the word under your cursor.
-- This is where a variable was first declared, or where a function is defined, etc.
-- To jump back, press <C-t>.
map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
-- WARN: This is not Goto Definition, this is Goto Declaration.
-- For example, in C this would take you to the header.
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
-- Fuzzy find all the symbols in your current document.
-- Symbols are things like variables, functions, types, etc.
map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols')
-- Fuzzy find all the symbols in your current workspace.
-- Similar to document symbols, except searches over your entire project.
map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols')
-- Jump to the type of the word under your cursor.
-- Useful when you're not sure what type a variable is and you want to see
-- the definition of its *type*, not where it was *defined*.
map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition')
-- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10)
@@ -116,7 +59,7 @@ return {
-- When you move your cursor, the highlights will be cleared (the second autocommand).
local client = vim.lsp.get_client_by_id(event.data.client_id)
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
local highlight_augroup = vim.api.nvim_create_augroup('lsp-highlight', { clear = false })
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
buffer = event.buf,
group = highlight_augroup,
@@ -130,18 +73,14 @@ return {
})
vim.api.nvim_create_autocmd('LspDetach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }),
group = vim.api.nvim_create_augroup('lsp-detach', { clear = true }),
callback = function(event2)
vim.lsp.buf.clear_references()
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf }
vim.api.nvim_clear_autocmds { group = 'lsp-highlight', buffer = event2.buf }
end,
})
end
-- The following code creates a keymap to toggle inlay hints in your
-- code, if the language server you are using supports them
--
-- This may be unwanted, since they displace some of your code
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then
map('<leader>th', function()
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
@@ -150,8 +89,6 @@ return {
end,
})
-- Diagnostic Config
-- See :help vim.diagnostic.Opts
vim.diagnostic.config {
severity_sort = true,
float = { border = 'rounded', source = 'if_many' },
@@ -179,14 +116,13 @@ return {
},
}
-- LSP servers and clients are able to communicate to each other what features they support.
-- By default, Neovim doesn't support everything that is in the LSP specification.
-- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities.
-- So, we create new capabilities with blink.cmp, and then broadcast that to the servers.
local capabilities = require('blink.cmp').get_lsp_capabilities()
-- vim.lsp.config['phpantom'] = {
-- filetypes = { 'php' },
-- cmd = { 'phpantom_lsp' },
-- root_markers = { 'composer.json', '.git' },
-- }
-- Enable the following language servers
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
--
-- Add any additional override configuration in the following tables. Available keys are:
-- - cmd (table): Override the default command used to start the server
@@ -194,68 +130,101 @@ return {
-- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features.
-- - settings (table): Override the default settings passed when initializing the server.
-- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/
local servers = {
-- clangd = {},
-- gopls = {},
-- pyright = {},
-- rust_analyzer = {},
-- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs
--
-- Some languages (like typescript) have entire language plugins that can be useful:
-- https://github.com/pmizio/typescript-tools.nvim
--
-- But for many setups, the LSP (`ts_ls`) will work just fine
-- ts_ls = {},
--
local mason_registry = require 'mason-registry'
local vue_language_server_path = vim.fn.expand '$MASON/packages/vue-language-server/node_modules/@vue/language-server'
local servers = {
clangd = {},
pyright = {},
rust_analyzer = {},
lua_ls = {
-- cmd = { ... },
-- filetypes = { ... },
-- capabilities = {},
settings = {
Lua = {
completion = {
callSnippet = 'Replace',
},
-- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings
-- diagnostics = { disable = { 'missing-fields' } },
},
},
},
phpantom_lsp = {
filetypes = { 'php' },
cmd = { 'phpantom_lsp' },
root_markers = { 'composer.json', '.git' },
},
vtsls = {
settings = {
vtsls = {
tsserver = {
globalPlugins = {
{
name = '@vue/typescript-plugin',
location = vue_language_server_path,
languages = { 'vue' },
configNamespace = 'typescript',
},
},
},
},
javascript = {
preferences = {
importModuleSpecifierPreference = 'non-relative',
importModuleSpecifierEnding = 'js',
},
},
},
filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
},
['vue-language-server'] = {
on_init = function(client)
client.handlers['tsserver/request'] = function(_, result, context)
local clients = vim.lsp.get_clients { bufnr = context.bufnr, name = 'vtsls' }
if #clients == 0 then
vim.notify('Could not find `vtsls` lsp client, `vue-language-server` would not work without it.', vim.log.levels.ERROR)
return
end
local ts_client = clients[1]
local param = unpack(result)
local id, command, payload = unpack(param)
ts_client:exec_cmd({
title = 'vue_request_forward', -- You can give title anything as it's used to represent a command in the UI, `:h Client:exec_cmd`
command = 'typescript.tsserverRequest',
arguments = {
command,
payload,
},
}, { bufnr = context.bufnr }, function(_, r)
local response_data = { { id, r.body } }
---@diagnostic disable-next-line: param-type-mismatch
client:notify('tsserver/response', response_data)
end)
end
end,
},
}
-- Ensure the servers and tools above are installed
--
-- To check the current status of installed tools and/or manually install
-- other tools, you can run
-- :Mason
--
-- You can press `g?` for help in this menu.
--
-- `mason` had to be setup earlier: to configure its options see the
-- `dependencies` table for `nvim-lspconfig` above.
--
-- You can add other tools here that you want Mason to install
-- for you, so that they are available from within Neovim.
local ensure_installed = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, {
'stylua', -- Used to format Lua code
'blade-formatter',
'eslint_d',
'pint',
})
-- LSP servers and clients are able to communicate to each other what features they support.
-- By default, Neovim doesn't support everything that is in the LSP specification.
-- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities.
-- So, we create new capabilities with blink.cmp, and then broadcast that to the servers.
local capabilities = require('blink.cmp').get_lsp_capabilities()
for name, cfg in pairs(servers) do
cfg.capabilities = vim.tbl_deep_extend('force', {}, capabilities, cfg.capabilities or {})
vim.lsp.config(name, cfg) -- new Neovim 0.11 API
end
require('mason-tool-installer').setup { ensure_installed = ensure_installed }
require('mason-lspconfig').setup {
ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer)
automatic_installation = false,
handlers = {
function(server_name)
local server = servers[server_name] or {}
-- This handles overriding only values explicitly passed
-- by the server configuration above. Useful when disabling
-- certain features of an LSP (for example, turning off formatting for ts_ls)
server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {})
require('lspconfig')[server_name].setup(server)
end,
},
}
require('mason').setup {}
require('mason-lspconfig').setup {}
end,
}
+43 -7
View File
@@ -1,6 +1,6 @@
-- Collection of various small independent plugins/modules
return {
"echasnovski/mini.nvim",
'echasnovski/mini.nvim',
config = function()
-- Better Around/Inside textobjects
--
@@ -8,28 +8,64 @@ return {
-- - va) - [V]isually select [A]round [)]paren
-- - yinq - [Y]ank [I]nside [N]ext [Q]uote
-- - ci' - [C]hange [I]nside [']quote
require("mini.ai").setup({ n_lines = 500 })
require('mini.ai').setup { n_lines = 500 }
-- Add/delete/replace surroundings (brackets, quotes, etc.)
--
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
-- - sd' - [S]urround [D]elete [']quotes
-- - sr)' - [S]urround [R]eplace [)] [']
require("mini.surround").setup()
require('mini.surround').setup {
mappings = {
add = 'ys',
delete = 'ds',
replace = 'cs',
},
}
require('mini.pairs').setup()
require('mini.jump').setup {
mappings = {
repeat_jump = ':',
},
}
local MiniJump2d = require 'mini.jump2d'
MiniJump2d.setup {
spotter = MiniJump2d.gen_spotter.union(
MiniJump2d.gen_spotter.pattern('[([{][^$]', 'end'),
MiniJump2d.gen_spotter.pattern('%$.', 'end'),
MiniJump2d.gen_spotter.pattern('->.', 'end'),
MiniJump2d.gen_spotter.pattern('^%s*%S', 'end')
),
mappings = {
start_jumping = 'S',
},
allowed_lines = {
blank = false,
cursor_at = false,
fold = false,
},
}
require('mini.splitjoin').setup()
require('mini.map').setup()
-- Simple and easy statusline.
-- You could remove this setup call if you don't like it,
-- You could remove this setup call i you don't like it,
-- and try some other statusline plugin
local statusline = require("mini.statusline")
local statusline = require 'mini.statusline'
-- set use_icons to true if you have a Nerd Font
statusline.setup({ use_icons = vim.g.have_nerd_font })
statusline.setup { use_icons = vim.g.have_nerd_font }
-- You can configure sections in the statusline by overriding their
-- default behavior. For example, here we set the section for
-- cursor location to LINE:COLUMN
---@diagnostic disable-next-line: duplicate-set-field
statusline.section_location = function()
return "%2l:%-2v"
return '%2l:%-2v'
end
-- ... and there is more!
-28
View File
@@ -1,28 +0,0 @@
-- Neo-tree is a Neovim plugin to browse the file system
-- https://github.com/nvim-neo-tree/neo-tree.nvim
return {
'nvim-neo-tree/neo-tree.nvim',
version = '*',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
'MunifTanjim/nui.nvim',
},
cmd = 'Neotree',
keys = {
{ '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
},
opts = {
filesystem = {
window = {
mappings = {
['\\'] = 'close_window',
},
},
filtered_items = {
hide_dotfiles = false,
},
},
},
}
+24
View File
@@ -0,0 +1,24 @@
-- Filesystem manager
-- require('helpers').edit_cf('po', '/lua/plugins/oil.lua')
--
vim.keymap.set('n', '-', '<CMD>Oil<CR>', { desc = 'Open parent directory' })
return {
'stevearc/oil.nvim',
---@module 'oil'
---@type oil.SetupOpts
opts = {
view_options = {
show_hidden = true,
},
keymaps = {
['<C-p>'] = false,
['-'] = false,
},
},
-- Optional dependencies
dependencies = { { 'echasnovski/mini.icons', opts = {} } },
-- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if you prefer nvim-web-devicons
-- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations.
lazy = false,
}
+3
View File
@@ -0,0 +1,3 @@
return {
'AlphaTechnolog/pywal.nvim',
}
+34
View File
@@ -0,0 +1,34 @@
vim.keymap.set("n", "<leader>q", function()
require("quicker").toggle()
end, { desc = "Toggle quickfix" })
vim.keymap.set("n", "<leader>l", function()
require("quicker").toggle({ loclist = true })
end, { desc = "Toggle loclist" })
return {
'stevearc/quicker.nvim',
ft = 'qf',
---@module "quicker"
---@type quicker.SetupOptions
opts = {},
config = function()
require('quicker').setup({
keys = {
{
">",
function()
require("quicker").expand({ before = 2, after = 2, add_to_existing = true })
end,
desc = "Expand quickfix context",
},
{
"<",
function()
require("quicker").collapse()
end,
desc = "Collapse quickfix context",
},
},
})
end,
}
+9
View File
@@ -0,0 +1,9 @@
return {
-- "ThePrimeagen/refactoring.nvim",
-- dependencies = {
-- "nvim-lua/plenary.nvim",
-- "nvim-treesitter/nvim-treesitter",
-- },
-- lazy = false,
-- opts = {},
}
+20
View File
@@ -0,0 +1,20 @@
return {
'MeanderingProgrammer/render-markdown.nvim',
dependencies = { 'nvim-treesitter/nvim-treesitter', 'echasnovski/mini.nvim' }, -- if you use the mini.nvim suite
-- dependencies = { 'nvim-treesitter/nvim-treesitter', 'echasnovski/mini.icons' }, -- if you use standalone mini plugins
-- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, -- if you prefer nvim-web-devicons
---@module 'render-markdown'
---@type render.md.UserConfig
ft = { 'markdown', 'codecompanion' },
config = function()
require('render-markdown').setup {
latex = {
enabled = true,
render_modes = true,
},
anti_conceal = {
enabled = false,
},
}
end,
}
+75
View File
@@ -0,0 +1,75 @@
return {
'folke/snacks.nvim',
priority = 1000,
lazy = false,
---@type snacks.Config
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
bigfile = { enabled = true },
dashboard = {
enabled = true,
preset = {
keys = {
{ icon = '', key = 'f', desc = 'Find File', action = ":lua Snacks.dashboard.pick('files')" },
{ icon = '', key = 'n', desc = 'New File', action = ':ene | startinsert' },
{ icon = '', key = 'g', desc = 'Find Text', action = ":lua Snacks.dashboard.pick('live_grep')" },
{ icon = '', key = 'r', desc = 'Recent Files', action = ":lua Snacks.dashboard.pick('oldfiles')" },
{ icon = '', key = 'c', desc = 'Config', action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})" },
-- { icon = " ", key = "s", desc = "Restore Session", section = "session" },
{ icon = '󰒲 ', key = 'L', desc = 'Lazy', action = ':Lazy', enabled = package.loaded.lazy ~= nil },
{ icon = '', key = 'q', desc = 'Quit', action = ':qa' },
},
},
sections = {
{ section = 'header' },
{ section = 'keys', gap = 1, padding = 1 },
{
pane = 2,
icon = '',
title = 'Projects',
section = 'projects',
indent = 2,
padding = 1,
session = false,
dirs = function()
return {
vim.fn.expand '~/Code/Sites/runcats',
vim.fn.expand '~/Code/Sites/moovaza',
vim.fn.expand '~/Code/Sites/tuxtoolkit',
vim.fn.expand '~/Code/Sites/chrisstarling',
vim.fn.stdpath 'config',
}
end,
},
{ pane = 2, icon = '', title = 'Recent Files', section = 'recent_files', indent = 2, padding = 1 },
{
pane = 2,
icon = '',
title = 'Git Status',
section = 'terminal',
enabled = function()
return Snacks.git.get_root() ~= nil
end,
cmd = 'git status --short --branch --renames',
height = 5,
padding = 1,
ttl = 5 * 60,
indent = 3,
},
},
},
indent = { enabled = true },
input = { enabled = true },
notifier = { enabled = true },
quickfile = { enabled = true },
scope = { enabled = true },
-- scroll = { enabled = true },
statuscolumn = { enabled = true },
words = { enabled = true },
terminal = { enabled = true },
scratch = { enabled = true },
rename = { enabled = true },
},
}
+28
View File
@@ -0,0 +1,28 @@
return {
'L3MON4D3/LuaSnip',
version = '2.*',
build = (function()
-- Build Step is needed for regex support in snippets.
-- This step is not supported in many windows environments.
-- Remove the below condition to re-enable on windows.
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
return
end
return 'make install_jsregexp'
end)(),
config = function()
local ls = require 'luasnip'
ls.filetype_extend('vue', { 'javascript' })
ls.filetype_extend('typescript', { 'javascript' })
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
require('luasnip.loaders.from_lua').load {
paths = { snippets_dir },
}
ls.setup {
update_events = 'TextChanged,TextChangedI',
enable_autosnippets = true,
}
end,
opts = {},
}
+6
View File
@@ -0,0 +1,6 @@
return {
'lambdalisue/vim-suda',
config = function()
vim.g.suda_smart_edit = 1
end,
}
+54 -37
View File
@@ -1,27 +1,27 @@
-- Fuzzy Finder (files, lsp, etc)
-- See :help telescope
return {
"nvim-telescope/telescope.nvim",
event = "VimEnter",
'nvim-telescope/telescope.nvim',
event = 'VimEnter',
dependencies = {
"nvim-lua/plenary.nvim",
'nvim-lua/plenary.nvim',
{ -- If encountering errors, see telescope-fzf-native README for installation instructions
"nvim-telescope/telescope-fzf-native.nvim",
'nvim-telescope/telescope-fzf-native.nvim',
-- `build` is used to run some command when the plugin is installed/updated.
-- This is only run then, not every time Neovim starts up.
build = "make",
build = 'make',
-- `cond` is a condition used to determine whether this plugin should be
-- installed and loaded.
cond = function()
return vim.fn.executable("make") == 1
return vim.fn.executable 'make' == 1
end,
},
{ "nvim-telescope/telescope-ui-select.nvim" },
{ 'nvim-telescope/telescope-ui-select.nvim' },
-- Useful for getting pretty icons, but requires a Nerd Font.
{ "nvim-tree/nvim-web-devicons", enabled = vim.g.have_nerd_font },
{ 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font },
},
config = function()
-- Telescope is a fuzzy finder that comes with a lot of different things that
@@ -45,7 +45,7 @@ return {
-- [[ Configure Telescope ]]
-- See `:help telescope` and `:help telescope.setup()`
require("telescope").setup({
require('telescope').setup {
-- You can put your default mappings / updates / etc. in here
-- All the info you're looking for is in `:help telescope.setup()`
--
@@ -56,50 +56,67 @@ return {
-- },
-- pickers = {}
extensions = {
["ui-select"] = {
require("telescope.themes").get_dropdown(),
['ui-select'] = {
require('telescope.themes').get_dropdown(),
},
},
})
defaults = {
mappings = {
i = {
-- Insert mode mappings for Telescope
['<C-j>'] = 'move_selection_next',
['<C-k>'] = 'move_selection_previous',
},
n = {
-- Normal mode mappings for Telescope
['<C-j>'] = 'move_selection_next',
['<C-k>'] = 'move_selection_previous',
},
},
file_ignore_patterns = {
'.obsidian',
},
},
}
-- Enable Telescope extensions if they are installed
pcall(require("telescope").load_extension, "fzf")
pcall(require("telescope").load_extension, "ui-select")
pcall(require('telescope').load_extension, 'fzf')
pcall(require('telescope').load_extension, 'ui-select')
-- See `:help telescope.builtin`
local builtin = require("telescope.builtin")
vim.keymap.set("n", "<leader>sh", builtin.help_tags, { desc = "[S]earch [H]elp" })
vim.keymap.set("n", "<leader>sk", builtin.keymaps, { desc = "[S]earch [K]eymaps" })
vim.keymap.set("n", "<leader>sf", builtin.find_files, { desc = "[S]earch [F]iles" })
vim.keymap.set("n", "<leader>ss", builtin.builtin, { desc = "[S]earch [S]elect Telescope" })
vim.keymap.set("n", "<leader>sw", builtin.grep_string, { desc = "[S]earch current [W]ord" })
vim.keymap.set("n", "<leader>sg", builtin.live_grep, { desc = "[S]earch by [G]rep" })
vim.keymap.set("n", "<leader>sd", builtin.diagnostics, { desc = "[S]earch [D]iagnostics" })
vim.keymap.set("n", "<leader>sr", builtin.resume, { desc = "[S]earch [R]esume" })
vim.keymap.set("n", "<leader>s.", builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
vim.keymap.set("n", "<leader><leader>", builtin.buffers, { desc = "[ ] Find existing buffers" })
local builtin = require 'telescope.builtin'
vim.keymap.set('n', '<leader>sh', builtin.help_tags, { desc = '[S]earch [H]elp' })
vim.keymap.set('n', '<leader>sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' })
vim.keymap.set('n', '<leader>sf', builtin.find_files, { desc = '[S]earch [F]iles' })
vim.keymap.set('n', '<leader>ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' })
vim.keymap.set('n', '<leader>sw', builtin.grep_string, { desc = '[S]earch current [W]ord' })
vim.keymap.set('n', '<leader>sg', builtin.live_grep, { desc = '[S]earch by [G]rep' })
vim.keymap.set('n', '<leader>sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' })
vim.keymap.set('n', '<leader>sr', builtin.resume, { desc = '[S]earch [R]esume' })
vim.keymap.set('n', '<leader>s.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' })
-- Slightly advanced example of overriding default behavior and theme
vim.keymap.set("n", "<leader>/", function()
vim.keymap.set('n', '<leader>/', function()
-- You can pass additional configuration to Telescope to change the theme, layout, etc.
builtin.current_buffer_fuzzy_find(require("telescope.themes").get_dropdown({
builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
winblend = 10,
previewer = false,
}))
end, { desc = "[/] Fuzzily search in current buffer" })
})
end, { desc = '[/] Fuzzily search in current buffer' })
-- It's also possible to pass additional configuration options.
-- See `:help telescope.builtin.live_grep()` for information about particular keys
vim.keymap.set("n", "<leader>s/", function()
builtin.live_grep({
vim.keymap.set('n', '<leader>s/', function()
builtin.live_grep {
grep_open_files = true,
prompt_title = "Live Grep in Open Files",
})
end, { desc = "[S]earch [/] in Open Files" })
prompt_title = 'Live Grep in Open Files',
}
end, { desc = '[S]earch [/] in Open Files' })
-- Shortcut for searching your Neovim configuration files
vim.keymap.set("n", "<leader>sn", function()
builtin.find_files({ cwd = vim.fn.stdpath("config") })
end, { desc = "[S]earch [N]eovim files" })
vim.keymap.set('n', '<leader>sn', function()
builtin.find_files { cwd = vim.fn.stdpath 'config' }
end, { desc = '[S]earch [N]eovim files' })
end,
}
+27
View File
@@ -0,0 +1,27 @@
require('helpers').edit_cf('pt', '/lua/plugins/test.lua')
return {
'nvim-neotest/neotest',
dependencies = {
'V13Axel/neotest-pest',
},
config = function()
require('neotest').setup {
adapters = {
require 'neotest-pest' {
sail_enabled = function()
return false
end,
parallel = 8,
pest_cmd = function()
local cmd = vim.g.neotest_pest_cmd or { 'vendor/bin/pest' }
if vim.g.neotest_debug then
cmd = { 'sh', '-c', 'XDEBUG_MODE=debug exec ' .. table.concat(cmd, ' ') .. ' "$@"' }
end
return cmd
end,
},
},
}
end,
}
+3 -3
View File
@@ -1,7 +1,7 @@
-- Highlight todo, notes, etc in comments
return {
"folke/todo-comments.nvim",
event = "VimEnter",
dependencies = { "nvim-lua/plenary.nvim" },
'folke/todo-comments.nvim',
event = 'VimEnter',
dependencies = { 'nvim-lua/plenary.nvim' },
opts = { signs = false },
}
+8
View File
@@ -0,0 +1,8 @@
return {
'nvim-treesitter/nvim-treesitter-textobjects',
branch = 'main',
config = function()
-- put your config here
end,
}
+23 -21
View File
@@ -1,15 +1,17 @@
-- Highlight, edit, and navigate code
return {
'nvim-treesitter/nvim-treesitter',
branch = 'main',
build = ':TSUpdate',
main = 'nvim-treesitter.configs', -- Sets main module to use for opts
-- [[ Configure Treesitter ]] See `:help nvim-treesitter`
opts = {
ensure_installed = {
config = function()
local langs = {
'bash',
'zsh',
'c',
'diff',
'html',
'latex',
'lua',
'luadoc',
'markdown',
@@ -17,22 +19,22 @@ return {
'query',
'vim',
'vimdoc',
},
-- Autoinstall languages that are not installed
auto_install = true,
highlight = {
enable = true,
-- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules.
-- If you are experiencing weird indenting issues, add the language to
-- the list of additional_vim_regex_highlighting and disabled languages for indent.
additional_vim_regex_highlighting = { 'ruby' },
},
indent = { enable = true, disable = { 'ruby' } },
},
-- There are additional nvim-treesitter modules that you can use to interact
-- with nvim-treesitter. You should go explore a few and see what interests you:
--
-- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod`
-- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context
-- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects
'php',
'yaml',
'vue',
'javascript',
'typescript',
'css',
'blade',
}
require('nvim-treesitter').install(langs)
vim.api.nvim_create_autocmd('FileType', {
pattern = langs,
callback = function()
vim.treesitter.start()
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end,
})
end,
}
+10
View File
@@ -0,0 +1,10 @@
return {
'Wansmer/treesj',
lazy = true,
dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter`
config = function()
require('treesj').setup({
use_default_keymaps = false,
})
end,
}
+9
View File
@@ -0,0 +1,9 @@
-- For when I'm ready
return {
-- "gbprod/yanky.nvim",
-- opts = {
-- -- your configuration comes here
-- -- or leave it empty to use the default settings
-- -- refer to the configuration section below
-- },
}
+26
View File
@@ -0,0 +1,26 @@
---@type LazySpec
return {
'mikavilpas/yazi.nvim',
version = '*', -- use the latest stable version
event = 'VeryLazy',
dependencies = {
{ 'nvim-lua/plenary.nvim', lazy = true },
},
keys = {
-- 👇 in this section, choose your own keymappings!
{
-- Open in the current working directory
'\\',
'<cmd>Yazi cwd<cr>',
desc = "Open the file manager in nvim's working directory",
},
},
---@type YaziConfig | {}
opts = {
-- if you want to open yazi instead of netrw, see below for more info
open_for_directories = false,
keymaps = {
show_help = '<f1>',
},
},
}
+79
View File
@@ -0,0 +1,79 @@
-- Project specific settings
local M = {}
-- Helper to create mappings
local helpers = require 'helpers'
local map = helpers.map
local function relevant_directory_from_cwd(cwd)
local basename = vim.fn.fnamemodify(cwd, ':t')
local nested_folder_names = { 'server', 'frontend', 'frontend2', 'client', 'backend' }
if vim.tbl_contains(nested_folder_names, basename) then
local parent = vim.fn.fnamemodify(cwd, ':h')
return relevant_directory_from_cwd(parent)
end
return cwd
end
-- Get the last folder name from a path
local function project_name_from_dir(dir)
return vim.fn.fnamemodify(dir, ':t')
end
local last_applied = nil
function M.apply(cwd)
local dir = relevant_directory_from_cwd(cwd or vim.fn.getcwd())
local name = project_name_from_dir(dir)
if last_applied == name then
return
end
last_applied = name
-- Check if project lua file exists in nvim config path
if vim.fn.filereadable(vim.fn.stdpath 'config' .. '/lua/projects/' .. name .. '.lua') == 1 then
local setup = require('projects.' .. name)
helpers.edit_cf('w', '/lua/projects/' .. name .. '.lua')
setup(dir)
vim.notify(('Project config loaded: %s'):format(name), vim.log.levels.INFO, { title = 'projects.lua' })
-- Source the project file to apply any new settings
vim.api.nvim_create_autocmd({ 'BufWritePost' }, {
pattern = { vim.fn.stdpath 'config' .. '/lua/projects/' .. name .. '.lua' },
callback = function()
package.loaded['projects.' .. name] = nil
local setup = require('projects.' .. name)
setup(dir)
vim.notify(('Project config reloaded: %s'):format(name), vim.log.levels.INFO, { title = 'projects.lua' })
end,
})
end
end
-- Apply on startup and when the working directory changes
do
local grp = vim.api.nvim_create_augroup('ProjectConfig', { clear = true })
vim.api.nvim_create_autocmd('VimEnter', {
group = grp,
callback = function()
M.apply()
end,
})
vim.api.nvim_create_autocmd('DirChanged', {
group = grp,
callback = function(args)
-- args.file is the new cwd for DirChanged
M.apply(args and args.file or nil)
end,
})
end
-- Optional command to manually re-apply
vim.api.nvim_create_user_command('ProjectReload', function()
last_applied = nil
M.apply()
end, {})
+184
View File
@@ -0,0 +1,184 @@
local helpers = require 'helpers'
local map = helpers.map
local M = {}
local function command_with_dir(dir, cmd)
if dir then
return '!cd ' .. dir .. ' && ' .. cmd
end
return '!' .. cmd
end
local function make_laravel_file(dir, cmd)
local cwd = vim.fn.getcwd()
if dir then
vim.fn.chdir(dir)
end
vim.ui.input({ prompt = 'Make: ' .. cmd }, function(input)
if input == nil then
vim.fn.chdir(cwd)
return
end
local output = vim.system({ 'vendor/bin/sail', 'artisan', 'make:' .. cmd, input }):wait().stdout
local new_file = output:match '%[([%w%./]+)%]'
if new_file ~= nil then
vim.cmd('edit ' .. new_file)
end
vim.fn.chdir(cwd)
end)
end
local function get_scope_from_file(filename)
local ext = filename:match '%.(%w+)$'
local base_name = filename:match '^(%w+)%.?%w*$'
local extensionSuffixes = {
php = { 'Controller', 'Repository', 'StoreRequest', 'UpdateRequest', 'Request', 'Resource', 'Test', 'Observer', 'Policy', 'Seeder', 'Factory' },
['[jt]s'] = { 'Service' },
}
for suffix_type, _ in pairs(extensionSuffixes) do
if ext:match(suffix_type) then
local suffixes = extensionSuffixes[suffix_type]
for _, suffix in ipairs(suffixes) do
local scope = base_name:match('^(%w+)' .. suffix .. '$')
if scope then
return scope
end
end
end
end
return base_name
end
local function navigate_using_suffix(suffix)
local scope = get_scope_from_file(vim.fn.expand '%:t')
local file_name = scope .. suffix
local file_path = vim.system({ 'git', 'ls-files', file_name, '**/' .. file_name }):wait().stdout
if file_path ~= '' then
vim.cmd('edit ' .. file_path)
else
vim.notify('File ' .. file_name .. ' not found in git ls-files', vim.log.levels.ERROR)
end
end
local function create_navigation_maps(maps)
for key, suffix_and_name in pairs(maps) do
map('<Leader>n' .. key, function()
navigate_using_suffix(suffix_and_name[1])
end, { desc = 'Navigate to relevant ' .. suffix_and_name[2] })
end
end
local function create_bookmark_maps(maps)
for key, bookmark in pairs(maps) do
helpers.create_bookmark(key, bookmark)
end
end
local function laravel_bookmarks_with_dir(dir)
create_bookmark_maps {
['e'] = dir .. '.env',
['l'] = dir .. 'storage/logs/laravel.log',
['w'] = dir .. 'routes/web.php',
['a'] = dir .. 'routes/api.php',
['m'] = dir .. 'database/migrations',
['dc'] = dir .. 'app/Core/',
['dd'] = dir .. 'app/Data/',
['dE'] = dir .. 'app/Enums/',
['de'] = dir .. 'app/Events/',
['dh'] = dir .. 'app/Http/',
['dj'] = dir .. 'app/Jobs/',
['dl'] = dir .. 'app/Listeners/',
['dM'] = dir .. 'app/Mail/',
['dm'] = dir .. 'app/Models/',
['dn'] = dir .. 'app/Notifications/',
['do'] = dir .. 'app/Observers/',
['dp'] = dir .. 'app/Providers/',
['pa'] = dir .. 'app/Providers/AppServiceProvider.php',
['pe'] = dir .. 'app/Providers/EventServiceProvider.php',
['cA'] = dir .. 'config/app.php',
['ca'] = dir .. 'config/auth.php',
['cb'] = dir .. 'config/broadcasting.php',
['cd'] = dir .. 'config/database.php',
['cf'] = dir .. 'config/filesystems.php',
['ch'] = dir .. 'config/filesystems.php',
['cl'] = dir .. 'config/logging.php',
['cm'] = dir .. 'config/mail.php',
['cq'] = dir .. 'config/queue.php',
['cS'] = dir .. 'config/services.php',
['cs'] = dir .. 'config/session.php',
}
end
local function laravel_utils(dir)
map('<Leader>D', function()
helpers.open_term {
cmd = dir .. 'vendor/bin/var-dump-server',
buf_opts = {
bufhidden = 'hide',
modifiable = false,
},
}
end, { desc = 'Open dump-server window' })
end
local function laravel_keymaps(dir)
map('sl ', command_with_dir(dir, 'vendor/bin/sail '), { desc = 'Run sail command' }, 'c')
map('art ', command_with_dir(dir, 'php artisan '), { desc = 'Run artisan command' }, 'c')
map('sart ', command_with_dir(dir, 'vendor/bin/sail artisan '), { desc = 'Run artisan command with sail' }, 'c')
map('cmp ', command_with_dir(dir, 'composer '), { desc = 'Run composer script' }, 'c')
map('<Leader>pm', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan migrate<CR>'))
map('<Leader>pr', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan migrate:rollback<CR>'))
map('<Leader>pM', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan make:'))
create_navigation_maps {
['m'] = { '.php', 'model' },
['c'] = { 'Controller.php', 'controller' },
['p'] = { 'Policy.php', 'policy' },
['R'] = { 'Resource.php', 'resource' },
['r'] = { 'Request.php', 'request' },
['t'] = { 'Test.php', 'test file' },
}
if dir == nil then
dir = ''
end
laravel_bookmarks_with_dir(dir)
end
local function laravel_makes(dir)
for key, name in pairs {
c = 'controller',
d = 'data',
e = 'event',
f = 'factory',
j = 'job',
l = 'listener',
ma = 'mail',
mi = 'migration',
mo = 'model',
mw = 'middleware',
n = 'notification',
o = 'observer',
pi = 'model --pivot',
po = 'policy',
pr = 'provider',
t = 'test --pest',
v = 'view',
x = 'exception',
} do
map('<Leader>m' .. key, function()
make_laravel_file(dir, name)
end, { desc = 'Make and navigate to relevant ' .. name })
end
end
M.laravel_keymaps = laravel_keymaps
M.laravel_makes = laravel_makes
M.laravel_utils = laravel_utils
M.laravel_bookmarks = laravel_bookmarks_with_dir
return M
+106
View File
@@ -0,0 +1,106 @@
local laravel_utils = require 'projects.framework_utils.laravel'
local helpers = require 'helpers'
local map = helpers.map
local create_bookmark = helpers.create_bookmark
local function switch_to(dir)
if vim.fn.getcwd() == dir then
return
end
vim.fn.chdir(dir)
vim.notify('Changed working directory to ' .. dir, vim.log.levels.INFO, { title = 'hylark.lua' })
end
return function(dir)
local function switch_to_server()
switch_to(dir .. '/server')
end
local function switch_to_frontend()
switch_to(dir .. '/frontend2')
end
local function switch_to_root()
switch_to(dir)
end
local function compile_typescript()
vim.fn.jobstart('php artisan typescript:transform', { cwd = dir .. '/server', stdout_buffered = true })
vim.notify('Compiling typescript types', vim.log.levels.INFO, { title = 'hylark.lua' })
end
map('<leader>pl', ':cexpr system("vendor/bin/phpstan analyse --no-progress --error-format=raw --memory-limit=2G -vv") <CR>', { desc = 'Run lint' })
map('<leader>T', function()
helpers.open_term { cmd = 'lazysql pgsql://homestead:password@localhost:5432/homestead' }
end, { desc = 'Open database manager' })
map('yrn ', '!cd frontend && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pm', ':vendor/bin/sail composer migrate<CR>')
map('<Leader>pcs', switch_to_server, { desc = 'Change working directory to server' })
map('<Leader>pcf', switch_to_frontend, { desc = 'Change working directory to frontend2' })
map('<Leader>pcr', switch_to_root, { desc = 'Change working directory to root' })
map('<Leader>pt', compile_typescript, { desc = 'Compile typescript' })
vim.api.nvim_create_autocmd({ 'BufWritePost' }, {
pattern = { '*.php', '.env', '.graphql' },
callback = function()
if not vim.fn.expand('%:p'):match(dir .. '/server/') then
vim.fn.jobstart('vendor/bin/sail artisan octane:reload', { stdout_buffered = true })
vim.fn.jobstart('vendor/bin/sail artisan horizon:terminate', { stdout_buffered = true })
end
if vim.fn.search '#\\[TypeScript\\]' ~= 0 then
compile_typescript()
end
end,
})
vim.api.nvim_create_autocmd({ 'BufWritePre' }, {
pattern = { '*.js', '*.ts', '*.vue' },
callback = function(args)
vim.env.ESLINT_D_PPID = vim.fn.getpid()
local cwd = vim.fn.getcwd()
if vim.fn.expand('%:p'):match(dir .. '/frontend2/') then
cwd = dir .. '/frontend2/'
end
require('helpers').format_buffer('eslint_d', args.buf, cwd)
end,
})
vim.api.nvim_create_autocmd({ 'BufWritePre' }, {
pattern = { '*.php' },
callback = function(args)
local cwd = vim.fn.getcwd()
if vim.fn.expand('%:p'):match(dir .. '/server/') then
cwd = dir .. '/server/'
end
require('helpers').format_buffer('pint', args.buf, cwd)
end,
})
vim.api.nvim_create_autocmd({ 'BufWritePost' }, {
pattern = { '.graphql' },
callback = function()
vim.fn.jobstart('vendor/bin/sail artisan lighthouse:clear-cache', { stdout_buffered = true })
end,
})
vim.api.nvim_create_autocmd({ 'BufEnter' }, {
pattern = { dir .. '**' },
callback = function()
if vim.fn.expand('%:p'):match(dir .. '/server/') then
switch_to_server()
elseif vim.fn.expand('%:p'):match(dir .. '/frontend2/') then
switch_to_frontend()
else
switch_to_root()
end
end,
})
laravel_utils.laravel_keymaps 'server/'
laravel_utils.laravel_makes 'server/'
laravel_utils.laravel_utils 'server/'
laravel_utils.laravel_bookmarks(dir .. '/server/')
create_bookmark('s', dir .. '/frontend2/src/types/api/server-types.d.ts')
end
+44
View File
@@ -0,0 +1,44 @@
local laravel_utils = require 'projects.framework_utils.laravel'
local helpers = require 'helpers'
local map = helpers.map
local create_bookmark = helpers.create_bookmark
return function(dir)
map(
'<leader>pl',
':cexpr system("cd server && vendor/bin/phpstan analyse --no-progress --error-format=raw --memory-limit=2G -vv") <CR>',
{ desc = 'Run lint' }
)
map('<leader>T', function()
helpers.open_term { cmd = 'lazysql mysql://root@localhost:3306/runcats' }
end, { desc = 'Open database manager' })
map('s ', '!cd server && ', { desc = 'Run command in server directory' }, 'c')
map('c ', '!cd client && ', { desc = 'Run command in client directory' }, 'c')
map('yrn ', '!cd client && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pt', ':!cd server && php artisan typescript:transform --format<CR>', { desc = 'Compile typescript' })
vim.api.nvim_create_autocmd({ 'BufWritePre' }, {
pattern = { '*.php' },
callback = function(args)
helpers.format_buffer('pint', args.buf)
end,
})
vim.api.nvim_create_autocmd({ 'BufWritePre' }, {
pattern = { '*.js', '*.ts', '*.vue' },
callback = function(args)
helpers.format_buffer('eslint_d', args.buf)
end,
})
laravel_utils.laravel_keymaps 'server/'
laravel_utils.laravel_makes 'server/'
laravel_utils.laravel_utils 'server/'
laravel_utils.laravel_bookmarks 'server/'
create_bookmark('E', dir .. '/client/src/types/api/endpointMap.d.ts')
create_bookmark('q', dir .. '/client/quasar.config.ts')
create_bookmark('db', dir .. '/client/src/boot')
create_bookmark('ds', dir .. '/client/src/stores')
create_bookmark('dS', dir .. '/client/src/services')
end
+1
View File
@@ -0,0 +1 @@
return {}
+161
View File
@@ -0,0 +1,161 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = require 'snippets.snip_utils'
local tr = utils.tr
local etr = utils.etr
local atr = utils.atr
local ctr = utils.ctr
local bs = utils.bs
return {
s(etr('du ', 'Dump a variable to the console'), fmta('console.log(#~);', { i(0) })),
s(
etr('vue', 'Vue Single File Component skeleton'),
fmta(
[[
<template>
</template>
<script setup>
#~
</script>
<style scoped>
</style>
]],
{ i(0) }
)
),
-- bs(atr('t ', 'this'), fmta('this.#~', { i(0) })),
s(etr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
s(etr('const ', 'const declaration'), {
c(1, {
sn(nil, fmta('const #~ = #~;', { i(1), i(2) })),
sn(
nil,
fmta(
[[
const #~ = (#~) => {
#~
}
]],
{ i(1), i(2), i(3) }
)
),
}),
}),
s(etr('ref ', 'ref'), {
c(1, {
sn(nil, fmta('const #~ = ref(#~);', { i(1), i(2) })),
sn(
nil,
fmta(
[[
const #~ = ref<#~>(#~);
]],
{ i(1), i(2), i(3) }
)
),
}),
}),
s(etr('com ', 'computed'), {
c(1, {
sn(nil, fmta('const #~ = computed(() => #~);', { i(1), i(2) })),
sn(
nil,
fmta(
[[
const #~ = computed(() => {
#~
})
]],
{ i(1), i(2) }
)
),
}),
}),
s(
etr('fn ', 'function block'),
fmta(
[[
function #~(#~) {
#~
}
]],
{ i(1), i(2), i(0) }
)
),
bs(atr('fn ', 'function block'), {
c(1, {
sn(
nil,
fmta(
[[
(#~) => {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
bs(atr('afn ', 'async function block'), {
c(1, {
sn(
nil,
fmta(
[[
async (#~) => {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
async function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
}
+617
View File
@@ -0,0 +1,617 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = require 'snippets.snip_utils'
local tr = utils.tr
local etr = utils.etr
local Etr = utils.Etr
local atr = utils.atr
local ctr = utils.ctr
local bs = utils.bs
local function psr_namespace()
local path = vim.fn.expand '%'
-- Get the directory of the path
local dir = vim.fs.dirname(path)
-- Loop through parent directories to find composer.json
while dir ~= '/' and dir ~= nil do
local composer_json_path = dir .. '/composer.json'
if vim.fn.filereadable(composer_json_path) == 1 then
break
end
dir = vim.fs.dirname(dir)
end
-- If no composer.json found, return empty string
if dir == '/' or dir == nil then
return ''
end
-- Decode composer.json and get PSR-4 autoload mappings
local composer = vim.json.decode(vim.iter(vim.fn.readfile(dir .. '/composer.json')):join '')
local psr4 = composer['autoload'] and composer['autoload']['psr-4']
-- If no PSR-4 mappings, return empty string
if not psr4 then
return ''
end
-- Get the relative path from the composer.json directory
local relative_path = path:sub(#dir + 2)
-- Loop through PSR-4 mappings
for namespace, map in pairs(psr4) do
-- Check if the relative path matches the mapping
if relative_path:match('^' .. map:gsub('/', '%%/')) then
-- Extract the suffix of the path after the mapping, removing the filename
local suffix = relative_path:sub(#map + 1):match '^(.*)/[^/]+%.php$' or ''
local trimmed = namespace:gsub('\\$', '')
return trimmed .. (suffix ~= '' and ('\\' .. suffix:gsub('/', '\\')) or '')
end
end
end
local function class_name(args, snip)
local filename = snip.env.TM_FILENAME or ''
return filename:match '([^%.]+)' or 'ClassName'
end
return {
---------------
-- DEBUGGING --
---------------
s(etr('du ', 'Dump a variable to the dump server', { priority = 1001 }), fmta('dump(#~);', { i(0) })),
bs(etr('du ', 'Dump a variable to the dump server'), fmta('dump(#~)', { i(0) })),
s(etr('r ', 'ray', { priority = 1001 }), fmta('ray(#~);', { i(0) })),
bs(etr('r ', 'ray'), fmta('ray(#~)', { i(0) })),
s(etr('dt ', 'Dump PHPStan type definition'), fmta('\\PhpStan\\dumpType(#~);', { i(0) })),
s(
etr('ql ', 'Log all queries'),
fmta(
[[
\Illuminate\Support\Facades\DB::listen(function (\Illuminate\Database\Events\QueryExecuted $e) {
dump($e->sql, $e->bindings);
});
#~
]],
{ i(0) }
)
),
--------------
-- COMMENTS --
--------------
s(etr('/**', 'Docblock comment'), {
c(1, {
sn(
nil,
fmta(
[[
/**
* #~
*/
]],
{ i(1) }
)
),
sn(nil, fmta('/** #~ */', { i(1) })),
}),
}),
s(etr('@v', '@var docblock'), fmta('/** @var #~ $#~ */', { i(1), i(0) })),
s(ctr('@v', '@var docblock'), fmta('@var #~ $#~', { i(1), i(0) })),
s(Etr('@pi', '@phpstan-ignore'), fmta('// @phpstan-ignore #~ (#~)', { i(1), i(0) })),
s(ctr('* @pr', 'Class property docblock'), fmta('* @property #~ $#~', { i(1), i(0) })),
s(ctr('* @pb', 'Class boolean property docblock'), fmta('* @property bool $#~', { i(0) })),
s(ctr('* @pi', 'Class int property docblock'), fmta('* @property int $#~', { i(0) })),
s(ctr('* @ps', 'Class string property docblock'), fmta('* @property string $#~', { i(0) })),
s(ctr('* @pc', 'Class collection property docblock'), fmta('* @property \\Illuminate\\Database\\Eloquent\\Collection<#~> $#~', { i(1), i(0) })),
s(ctr('* @pd', 'Class date property docblock'), fmta('* @property \\Illuminate\\Support\\Carbon $#~', { i(0) })),
s(
etr('@pm', 'Model magic properties docblock'),
fmta(
[[
/**
* @property int $id
* #~
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
*
* Relationships
* #~
*/
]],
{ i(1), i(0) }
)
),
------------
-- SYNTAX --
------------
s(
etr('if ', 'if block'),
fmta(
[[
if (#~) {
#~
}
]],
{ i(1), i(0) }
)
),
s(
etr('fe ', 'foreach block'),
fmta(
[[
foreach (#~ as #~) {
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(etr('foreach', 'foreach block'), fmta('fe', {})),
s(
etr('for ', 'for block'),
fmta(
[[
for (#~; #~; #~) {
#~
}
]],
{ i(1, '$i'), i(2), i(3, '$i++'), i(0) }
)
),
s(etr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
-- s(atr(' use ', 'Add use to function'), fmta(' use (#~)', { i(0) })),
s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
bs(atr('fn ', 'Shorthand function block'), {
c(1, {
sn(nil, fmta('fn (#~) => #~', { i(1), i(2) })),
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
bs(atr('fun ', 'Shorthand function block'), {
c(1, {
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
function (#~) use (#~) {
#~
}
]],
{ i(1), i(2), i(3) }
)
),
}),
}),
-- s(
-- etr('con', 'Constructor function block'),
-- c(1, {
-- sn(
-- nil,
-- fmta(
-- [[
-- public function __construct(#~)
-- {
-- #~
-- }
-- ]],
-- { i(1), i(2) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- public function __construct(
-- #~
-- ) {
-- #~
-- }
-- ]],
-- { i(1), i(2) }
-- )
-- ),
-- })
-- ),
bs(atr('function', 'Shorthand function block'), fmta('fun', {})),
bs(atr('s%$', 'string type parameter'), fmta('string $#~', { i(0, 'var') })),
bs(atr('i%$', 'int type parameter'), fmta('int $#~', { i(0, 'var') })),
bs(atr('b%$', 'bool type parameter'), fmta('bool $#~', { i(0, 'var') })),
bs(atr('a%$', 'array type parameter'), fmta('array $#~', { i(0, 'var') })),
s(atr('$ ', 'Expand $this->'), fmta('$this->#~', { i(0) })),
bs(etr('am ', 'array_map function'), {
c(1, {
sn(nil, fmta('array_map(fn (#~) => #~, #~)', { i(2), i(3), i(1) })),
sn(
nil,
fmta(
[[
array_map(function (#~) {
#~
}, #~)
]],
{ i(2), i(0), i(1) }
)
),
}),
}),
bs(etr('array_map', 'array_map function'), fmta('am', {})),
bs(etr('af ', 'array_filter function'), {
c(1, {
sn(nil, fmta('array_filter(#~, fn (#~) => #~)', { i(1), i(2), i(3) })),
sn(
nil,
fmta(
[[
array_filter(#~, function (#~) {
#~
})
]],
{ i(1), i(2), i(0) }
)
),
}),
}),
bs(etr('array_filter', 'array_filter function'), fmta('af', {})),
s(
etr('php', 'php class'),
fmta(
[[
<?php
declare(strict_types=1);
namespace #~;
class #~
{
public function __construct()
{
#~
}
}
]],
{ f(psr_namespace, {}), f(class_name, {}), i(0) }
)
),
s(
etr('met', 'public class method'),
fmta(
[[
public function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('pmet', 'protected class method'),
fmta(
[[
protected function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('smet', 'public static class method'),
fmta(
[[
public static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('spmet', 'protected static class method'),
fmta(
[[
protected static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
-------------
-- PROJECT --
-------------
s(
etr('test', 'Create a test function'),
fmta(
[[
test('#~', function () {
#~
});
]],
{ i(1), i(0) }
)
),
s(
etr('it ', 'Create a test function'),
fmta(
[[
it('#~', function () {
#~
});
]],
{ i(1), i(0) }
)
),
s(etr('nn ', 'Assert not null'), fmta('Assert::notNull(#~);', { i(0) })),
s(etr('ast ', 'Assert string'), fmta('Assert::string(#~);', { i(0) })),
s(etr('ain ', 'Assert integer'), fmta('Assert::integer(#~);', { i(0) })),
s(etr('aio ', 'Assert instance of'), fmta('Assert::isInstanceOf(#~);', { i(0) })),
s(etr('at ', 'Assert true'), fmta('Assert::true(#~);', { i(0) })),
-------------
-- LARAVEL --
-------------
s(
etr('bt', 'belongsTo Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
*/
public function #~(): BelongsTo
{
return $this->belongsTo(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
*/
public function #~(): BelongsTo
{
return $this->belongsTo(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('hm', 'hasMany Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
*/
public function #~(): HasMany
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
*/
public function #~(): HasMany
{
return $this->hasOne(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('ho', 'hasOne Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
*/
public function #~(): HasOne
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
*/
public function #~(): HasOne
{
return $this->hasOne(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('bm', 'belongsToMany Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
*/
public function #~(): BelongsToMany
{
return $this->belongsToMany(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
*/
public function #~(): BelongsToMany
{
return $this->belongsToMany(#~::class, #~, #~);
}
]],
{ rep(1), i(2), i(1), i(3), i(4) }
)
),
})
),
-- s(
-- atr('->wr', 'Eloquent where method'),
-- c(0, {
-- sn(nil, fmta("->where('#~', #~)", { i(1), i(0) })),
-- sn(nil, fmta('->where(fn ($query) => #~)', { i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->where(function ($query) {
-- #~
-- })
-- ]],
-- { i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->where(function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- })
-- ),
-- s(atr('->wi', 'Eloquent where in method'), fmta("->whereIn('#~', #~)", { i(1), i(0) })),
-- s(atr('->wn', 'Eloquent where not in method'), fmta("->whereNotIn('#~', #~)", { i(1), i(0) })),
-- s(
-- atr('->wha', 'Eloquent where has method'),
-- c(0, {
-- sn(nil, fmta("->whereHas('#~')", { i(1) })),
-- sn(nil, fmta("->whereHas('#~', fn ($query) => #~)", { i(1), i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereHas('#~', function ($query) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereHas('#~', function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(2), i(0) }
-- )
-- ),
-- })
-- ),
-- s(
-- atr('->we', 'Eloquent where exists method'),
-- c(0, {
-- sn(nil, fmta('->whereExists(fn ($query) => #~)', { i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereExists(function ($query) {
-- #~
-- })
-- ]],
-- { i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereExists(function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- })
-- ),
}
+152
View File
@@ -0,0 +1,152 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local line_begin = require('luasnip.extras.conditions').line_begin
local line_end = require('luasnip.extras.conditions').line_end
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = {}
--- Check if the trigger is at the beginning of a line
---@param line_to_cursor string
---@param matched_trigger string
---@return boolean
utils.line_begin = function(line_to_cursor, matched_trigger)
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match '^%s*$'
end
--- Check if the trigger is on an empty line
---@param _ string
---@param matched_trigger string
---@return boolean
utils.empty_line = function(_, matched_trigger)
return vim.api.nvim_get_current_line():match('^%s*' .. vim.pesc(matched_trigger) .. '$')
end
--- Check if the trigger is at the start of a file
---@param line_to_cursor string
---@param matched_trigger string
---@return boolean
utils.file_begin = function(line_to_cursor, matched_trigger)
local line_number = vim.fn.line '.'
return line_number == 1 and line_begin(line_to_cursor, matched_trigger)
end
--- Check if the trigger is inside a string
---@return boolean
utils.in_string = function()
local node_type = vim.treesitter.get_node():type()
return node_type == 'string_content' or node_type == 'string'
end
--- Check if the trigger is inside a comment
---@return boolean
utils.in_comment = function()
local node_type = vim.treesitter.get_node():type()
return node_type == 'comment'
end
--- Check if the trigger is not inside a string or a comment
---@return boolean
utils.not_in_string_or_comment = function()
return (not utils.in_string()) and (not utils.in_comment())
end
--- Create a basic auto expand trigger
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.tr = function(trigger, description, options)
return vim.tbl_extend('force', {
trig = trigger,
desc = description,
snippetType = 'autosnippet',
}, options or {})
end
--- Create a trigger for an empty line snippet
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.etr = function(trigger, description, options)
return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.empty_line }, options or {}))
end
--- Create a trigger for a comment trigger
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.ctr = function(trigger, description, options)
return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.in_comment }, options or {}))
end
--- Create a trigger for a snippet to expand anywhere outside a string/comment
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.atr = function(trigger, description, options)
return utils.tr(
trigger,
description,
vim.tbl_extend('force', {
regTrig = true,
wordTrig = false,
condition = utils.not_in_string_or_comment,
}, options or {})
)
end
--- Create a trigger for a snippet to expand at the end of a line
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.Etr = function(trigger, description, options)
return utils.tr(
trigger,
description,
vim.tbl_extend('force', {
condition = line_end
}, options or {})
)
end
--- Create a snippet that will expand anywhere but in the middle of a word
---@param trigger any
---@param nodes any
---@param options? any
---@return table
utils.bs = function(trigger, nodes, options)
local btrigger
if type(trigger) == 'string' then
btrigger = utils.atr('([^%w_-])' .. trigger)
else
btrigger = vim.tbl_extend('keep', utils.atr('([^%w_-])' .. trigger.trig), trigger)
end
return ms(
{
trigger,
btrigger,
},
vim.list_extend({ fn(function(args, snip)
return snip.captures[1] or ''
end) }, nodes),
options
)
end
return utils
+16
View File
@@ -0,0 +1,16 @@
local M = {}
function M.open(name)
local titles = {
zsh = 'ZSH Cheat Sheet',
bash = 'Bash Cheat Sheet',
regex = 'RegExp Cheat Sheet',
}
local path = vim.fn.stdpath 'config' .. '/cheatsheets/' .. name .. '.md'
print('Opening cheat sheet: ' .. path)
require('../helpers').open_file_modal(path, titles[name] or name)
end
return M
+53
View File
@@ -0,0 +1,53 @@
local progress = require 'fidget.progress'
local M = {}
M.handles = {}
function M:store_progress_handle(id, handle)
M.handles[id] = handle
end
function M:pop_progress_handle(id)
local handle = M.handles[id]
M.handles[id] = nil
return handle
end
function M:create_progress_handle(request)
-- Ensure request.data and request.data.adapter exist before accessing them
local strategy = request.data and request.data.strategy or 'unknown'
local adapter_info = request.data and request.data.adapter or {}
return progress.handle.create {
title = ' Requesting assistance (' .. strategy .. ')',
message = 'In progress...',
lsp_client = {
name = M:llm_role_title(adapter_info),
},
}
end
function M:llm_role_title(adapter)
local parts = {}
-- Use adapter.formatted_name if available, otherwise default
local name = adapter.formatted_name or 'LLM'
table.insert(parts, name)
if adapter.model and adapter.model ~= '' then
table.insert(parts, '(' .. adapter.model .. ')')
end
return table.concat(parts, ' ')
end
function M:report_exit_status(handle, request)
-- Ensure request.data exists before accessing status
local status = request.data and request.data.status or 'unknown'
if status == 'success' then
handle.message = 'Completed'
elseif status == 'error' then
handle.message = ' Error'
else -- Includes "cancelled" or any other status
handle.message = '󰜺 Cancelled/Other'
end
end
return M
+8
View File
@@ -0,0 +1,8 @@
require('helpers').edit_cf('c', '/lua/visuals.lua')
local line_number_color = '#5d6487'
vim.cmd('highlight LineNr guifg=' .. line_number_color)
vim.cmd('highlight LineNrAbove guifg=' .. line_number_color)
vim.cmd('highlight LineNrBelow guifg=' .. line_number_color)
vim.api.nvim_set_hl(0, "CopilotSuggestion", { fg = "#888888", italic = true })
+3
View File
@@ -0,0 +1,3 @@
WRN 2026-07-03T16:02:54.215 c/nvim.57084.0 server_start:197: Failed to start server: operation not permitted: /var/folders/j3/6yv08_8s1s740ggr40_kgvrr0000gn/T/nvim.chris/esnddj/nvim.57725.0
WRN 2026-07-03T16:03:18.385 c/nvim.57084.0 server_start:197: Failed to start server: operation not permitted: /var/folders/j3/6yv08_8s1s740ggr40_kgvrr0000gn/T/nvim.chris/O4WnB1/nvim.57764.0
WRN 2026-07-14T11:43:01.105 c/nvim.17401.0 server_start:197: Failed to start server: operation not permitted: /var/folders/j3/6yv08_8s1s740ggr40_kgvrr0000gn/T/nvim.chris/KkEtYu/nvim.19436.0