diff --git a/README.md b/README.md index eb5a33d69bc..88d2ebb8809 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,18 @@ A personalized Neovim configuration based on [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim), tailored for Java and Go development with a focus on clean keybindings, git integration, and a minimal UI. +## Requirements + +- **Neovim 0.10+** (uses `vim.keymap`, `vim.diagnostic.config`, and other modern APIs) +- **JDK 21+** for Java LSP (jdtls) +- Nerd Font (JetBrainsMono recommended) + ## Quick Install One-liner that installs all dependencies and clones the config (supports **macOS**, **CentOS/RHEL**, and **Azure Linux/CBL-Mariner**): ```sh -sh -c "$(curl -fsSL https://raw.githubusercontent.com/advpetc/kickstart.nvim/master/install.sh)" +sh -c "$(curl -fsSL https://raw.githubusercontent.com/advpetc/kickstart.nvim/rdev-setup/install.sh)" ``` This will: @@ -26,7 +32,7 @@ If you prefer to install dependencies yourself: ```sh # 1. Clone the config -git clone https://github.com/advpetc/kickstart.nvim.git ~/.config/nvim +git clone -b rdev-setup https://github.com/advpetc/kickstart.nvim.git ~/.config/nvim # 2. Install dependencies (macOS example) brew install neovim ripgrep fd gh node go @@ -50,6 +56,26 @@ sudo dnf install -y git make gcc gcc-c++ unzip curl ripgrep fd-find nodejs +
Azure Linux / CBL-Mariner + +```sh +# Neovim (from GitHub release) +curl -fsSL https://github.com/neovim/neovim/releases/download/v0.10.4/nvim-linux-x86_64.tar.gz -o /tmp/nvim.tar.gz +sudo mkdir -p /opt/nvim && sudo tar -xzf /tmp/nvim.tar.gz -C /opt/nvim --strip-components=1 +sudo ln -sf /opt/nvim/bin/nvim /usr/local/bin/nvim + +# System tools (use tdnf on CBL-Mariner 2.0, dnf on Azure Linux 3.0) +sudo tdnf install -y git make gcc unzip curl ripgrep nodejs + +# fd (not in repos — install from GitHub release) +FD_VERSION=$(curl -fsSL https://api.github.com/repos/sharkdp/fd/releases/latest | grep '"tag_name"' | sed -E 's/.*"v?([^"]+)".*/\1/') +curl -fsSL "https://github.com/sharkdp/fd/releases/download/v${FD_VERSION}/fd-v${FD_VERSION}-x86_64-unknown-linux-gnu.tar.gz" -o /tmp/fd.tar.gz +tar -xzf /tmp/fd.tar.gz -C /tmp +sudo cp /tmp/fd-v${FD_VERSION}-x86_64-unknown-linux-gnu/fd /usr/local/bin/fd +``` + +
+ ## Plugins | Plugin | Purpose | @@ -213,11 +239,21 @@ Sessions are stored in `~/.local/state/nvim/sessions/` via `mini.sessions`: The Java configuration uses [nvim-jdtls](https://github.com/mfussenegger/nvim-jdtls) with: -- **JDK 21** (Microsoft build) at `/Library/Java/JavaVirtualMachines/jdk21.0.6-msft.jdk/Contents/Home` +- **JDK 21+** required (auto-detected, see resolution order below) - **Gradle & Maven** import support with source downloading - **DAP debugging** with hot code replace - **Workspace**: `~/.local/share/nvim/jdtls-workspace/` +### JDK Resolution Order + +1. `JDTLS_JAVA_HOME` environment variable (explicit override) +2. Known JDK 21 paths on Linux: + - `/export/apps/jdk/JDK-21_0_0-msft` (LinkedIn internal) + - `/usr/lib/jvm/java-21-openjdk` + - `/usr/lib/jvm/java-21-openjdk-amd64` +3. macOS: `/usr/libexec/java_home -v 21` +4. `JAVA_HOME` environment variable (fallback) + > Run `./gradlew build` before opening a project to generate required jars. > Use `jx` (`:JdtlsClearCache`) to reset the jdtls workspace if things go wrong. diff --git a/init.lua b/init.lua index a448d94cbb1..22c6235eb5e 100644 --- a/init.lua +++ b/init.lua @@ -222,12 +222,22 @@ vim.keymap.set('n', '', '', { desc = 'Move focus to the upper win vim.keymap.set('n', 'cp', function() local path = vim.fn.expand '%' vim.fn.setreg('+', path) + -- Also copy via OSC 52 for remote SSH sessions + local ok, osc52 = pcall(require, 'osc52') + if ok then + osc52.copy(path) + end print('Copied: ' .. path) end, { desc = '[C]opy file [P]ath (relative)' }) vim.keymap.set('n', 'cP', function() local path = vim.fn.expand '%:p' vim.fn.setreg('+', path) + -- Also copy via OSC 52 for remote SSH sessions + local ok, osc52 = pcall(require, 'osc52') + if ok then + osc52.copy(path) + end print('Copied: ' .. path) end, { desc = '[C]opy file [P]ath (absolute)' }) @@ -240,6 +250,11 @@ vim.keymap.set('n', 'cl', function() return end vim.fn.setreg('+', url) + -- Also copy via OSC 52 for remote SSH sessions + local ok, osc52 = pcall(require, 'osc52') + if ok then + osc52.copy(url) + end vim.notify('Copied: ' .. url, vim.log.levels.INFO) end, { desc = '[C]opy GitHub [L]ink' }) @@ -658,7 +673,9 @@ require('lazy').setup({ -- 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() + local capabilities = vim.lsp.protocol.make_client_capabilities() + local ok, blink = pcall(require, 'blink.cmp') + if ok then capabilities = vim.tbl_deep_extend('force', capabilities, blink.get_lsp_capabilities()) end -- Enable the following language servers -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. @@ -959,20 +976,8 @@ require('lazy').setup({ end, }, - { -- Highlight, edit, and navigate code - 'nvim-treesitter/nvim-treesitter', - config = function() - local filetypes = { 'bash', 'c', 'diff', 'html', 'java', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } - -- Only auto-install parsers if tree-sitter CLI is available - if vim.fn.executable 'tree-sitter' == 1 then - require('nvim-treesitter').install(filetypes) - end - vim.api.nvim_create_autocmd('FileType', { - pattern = filetypes, - callback = function() vim.treesitter.start() end, - }) - end, - }, + -- Note: Neovim 0.11+ has built-in treesitter support + -- Treesitter will be enabled automatically for supported filetypes -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the -- init.lua. If you want these files, they are in the repository, so you can just download them and diff --git a/install.sh b/install.sh index d9a3d00a3b3..70929bce0f3 100755 --- a/install.sh +++ b/install.sh @@ -10,7 +10,7 @@ # bash install.sh --help # show help # # One-liner (no clone needed): -# sh -c "$(curl -fsSL https://raw.githubusercontent.com/advpetc/kickstart.nvim/master/install.sh)" +# sh -c "$(curl -fsSL https://raw.githubusercontent.com/advpetc/kickstart.nvim/rdev-setup/install.sh)" # set -euo pipefail @@ -481,6 +481,125 @@ install_jdk() { esac } +# ─── Setup JDTLS_JAVA_HOME (LinkedIn environments) ─────────────────────────── + +setup_jdtls_java_home() { + log_step "JDTLS Java Configuration" + + local jdk_base_dir="/export/apps/jdk" + local selected_jdk="" + local selected_version=0 + local is_compatible=false + + # Check if the LinkedIn JDK directory exists + if [ ! -d "$jdk_base_dir" ]; then + log_info "JDK directory $jdk_base_dir not found — skipping JDTLS_JAVA_HOME setup" + log_info "If jdtls fails, set JDTLS_JAVA_HOME manually to your Java 21+ installation" + return 0 + fi + + # Scan for all JDK installations and find the best one + log_info "Scanning for Java installations in $jdk_base_dir..." + + while IFS= read -r jdk_dir; do + local jdk_path="$jdk_base_dir/$jdk_dir" + + # Skip if not a directory or no java binary + [ ! -d "$jdk_path" ] && continue + [ ! -x "$jdk_path/bin/java" ] && continue + + # Extract version number from directory name (e.g., JDK-21_0_0-msft -> 21) + local version_major + if [[ "$jdk_dir" =~ JDK-([0-9]+) ]]; then + version_major="${BASH_REMATCH[1]}" + else + continue + fi + + # Prefer Java 21+ (compatible with jdtls), but track highest version found + if [ "$version_major" -ge 21 ]; then + if [ "$version_major" -gt "$selected_version" ]; then + selected_jdk="$jdk_path" + selected_version="$version_major" + is_compatible=true + fi + elif [ "$version_major" -gt "$selected_version" ]; then + # Fallback: track highest version even if < 21 + selected_jdk="$jdk_path" + selected_version="$version_major" + fi + done < <(ls "$jdk_base_dir" 2>/dev/null) + + # No JDK found at all + if [ -z "$selected_jdk" ]; then + log_warn "No JDK installations found in $jdk_base_dir" + log_info "If jdtls fails, set JDTLS_JAVA_HOME manually to your Java 21+ installation" + return 0 + fi + + # Verify the selected JDK is actually executable + if ! "$selected_jdk/bin/java" -version &>/dev/null; then + log_warn "Selected JDK at $selected_jdk is not executable" + return 0 + fi + + # Provide appropriate feedback based on version + if [ "$is_compatible" = true ]; then + log_ok "Found Java $selected_version at $selected_jdk (compatible with jdtls)" + else + log_warn "Found Java $selected_version at $selected_jdk" + log_warn "jdtls requires Java 21+. LSP may fail to start." + log_info "Install Java 21+ and re-run this script, or set JDTLS_JAVA_HOME manually" + fi + + # Add to .bashrc if not already there + if [ -f "$HOME/.bashrc" ]; then + if grep -q "export JDTLS_JAVA_HOME=" "$HOME/.bashrc" 2>/dev/null; then + log_info "Updating JDTLS_JAVA_HOME in .bashrc..." + # Remove old entry and add new one + sed -i.bak '/export JDTLS_JAVA_HOME=/d' "$HOME/.bashrc" + sed -i.bak '/# Java.*for JDTLS/d' "$HOME/.bashrc" + else + log_info "Adding JDTLS_JAVA_HOME to .bashrc..." + fi + cat >> "$HOME/.bashrc" </dev/null; then + log_info "Updating JDTLS_JAVA_HOME in .zshrc..." + # Remove old entry and add new one + sed -i.bak '/export JDTLS_JAVA_HOME=/d' "$HOME/.zshrc" + sed -i.bak '/# Java.*for JDTLS/d' "$HOME/.zshrc" + else + log_info "Adding JDTLS_JAVA_HOME to .zshrc..." + fi + cat >> "$HOME/.zshrc" <y', require('osc52').copy_visual, { desc = 'Copy to system clipboard (OSC52)' }) + end, + }, +} diff --git a/lua/custom/plugins/git.lua b/lua/custom/plugins/git.lua index 6c0739cb73a..4dc3036f751 100644 --- a/lua/custom/plugins/git.lua +++ b/lua/custom/plugins/git.lua @@ -8,6 +8,8 @@ return { { 'gh', 'DiffviewFileHistory %', desc = 'Git file history' }, { 'gH', 'DiffviewFileHistory', desc = 'Git branch history' }, { 'gc', 'DiffviewClose', desc = 'Close diff view' }, + { 'gR', '!git reset --hard', desc = 'Git reset --hard (entire repo)' }, + { 'gr', '!git reset', desc = 'Git reset (unstage all, keep changes)' }, }, opts = { enhanced_diff_hl = true, diff --git a/lua/custom/plugins/java.lua b/lua/custom/plugins/java.lua index 8a15a3d6a90..694c90dcd1e 100644 --- a/lua/custom/plugins/java.lua +++ b/lua/custom/plugins/java.lua @@ -10,11 +10,22 @@ return { }, config = function() -- Resolve Java home for running jdtls (needs JDK 21+) - -- Priority: JDTLS_JAVA_HOME > JAVA_HOME > macOS java_home > java on PATH + -- Priority: JDTLS_JAVA_HOME > known JDK 21 locations > macOS java_home > JAVA_HOME local function resolve_java_home() - local home = vim.env.JDTLS_JAVA_HOME or vim.env.JAVA_HOME + -- Check explicit JDTLS_JAVA_HOME first + local home = vim.env.JDTLS_JAVA_HOME if home and home ~= '' then return home end + -- Check known JDK 21+ locations on Linux + local jdk21_paths = { + '/export/apps/jdk/JDK-21_0_0-msft', + '/usr/lib/jvm/java-21-openjdk', + '/usr/lib/jvm/java-21-openjdk-amd64', + } + for _, path in ipairs(jdk21_paths) do + if vim.fn.isdirectory(path) == 1 then return path end + end + if vim.fn.has 'mac' == 1 then -- Try JDK 21 first, then any version home = vim.fn.trim(vim.fn.system '/usr/libexec/java_home -v 21 2>/dev/null') @@ -24,6 +35,10 @@ return { if home ~= '' then return home end end + -- Fall back to JAVA_HOME (may not be JDK 21+) + home = vim.env.JAVA_HOME + if home and home ~= '' then return home end + local java_bin = vim.fn.exepath 'java' if java_bin ~= '' then return vim.fn.fnamemodify(vim.fn.resolve(java_bin), ':h:h') @@ -185,7 +200,12 @@ return { map('dx', dap.terminate, 'Terminate') end, - capabilities = require('blink.cmp').get_lsp_capabilities(), + capabilities = (function() + local caps = vim.lsp.protocol.make_client_capabilities() + local ok, blink = pcall(require, 'blink.cmp') + if ok then caps = vim.tbl_deep_extend('force', caps, blink.get_lsp_capabilities()) end + return caps + end)(), } jdtls.start_or_attach(config) @@ -197,8 +217,10 @@ return { callback = start_jdtls, }) - -- Start immediately for current buffer - start_jdtls() + -- Start immediately only if current buffer is a Java file + if vim.bo.filetype == 'java' then + start_jdtls() + end end, }, }