2025年10月29日 星期三

Prevent Debian from suspend

sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

 

sudo nano /etc/systemd/sleep.conf.d/nosuspend.conf

[Sleep]
AllowSuspend=no
AllowHibernation=no
AllowSuspendThenHibernate=no
AllowHybridSleep=no


gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0
gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0


sudo nano /etc/systemd/logind.conf

[Login]
HandleLidSwitch=ignore
HandleLidSwitchDocked=ignore


https://unix.stackexchange.com/questions/748759/disabling-suspend-etc-on-debian-12


/etc/gdm3/greeter.dconf-defaults

# Automatic suspend
# =================
[org/gnome/settings-daemon/plugins/power]
# - Time inactive in seconds before suspending with AC power
#   1200=20 minutes, 0=never
# sleep-inactive-ac-timeout=1200
# - What to do after sleep-inactive-ac-timeout
#   'blank', 'suspend', 'shutdown', 'hibernate', 'interactive' or 'nothing'
sleep-inactive-ac-type='blank'
# - As above but when on battery
# sleep-inactive-battery-timeout=1200
# sleep-inactive-battery-type='suspend'

 

2025年8月4日 星期一

NVIM key mapping

 To determine if a keymap is bound in Neovim, or to see what a specific key or key combination is mapped to, several methods can be employed:

  • Using the :map command (and its variants):
    • :map: Lists all mappings in all modes.
    • :nmap: Lists mappings specifically for Normal mode.
    • :vmap: Lists mappings for Visual mode.
    • :imap: Lists mappings for Insert mode.
    • :cmap: Lists mappings for Command-line mode.
    • To check a specific key, append it to the command, e.g., :map <Leader>s to see what <Leader>s is mapped to.
  • Using verbose map:
    • To see where a mapping was defined (e.g., in a plugin or your init.vim), use verbose map followed by the key or key sequence. For example, :verbose map <C-s> will show the mapping and the file it originated from.
  • Using mapcheck():
    • The mapcheck() function can be used in a script or on the command line to programmatically check if a mapping exists for a given key sequence. For example, :echo mapcheck('<C-s>') will return a non-empty string if a mapping exists for <C-s>.
  • Using maparg():
    • To get detailed information about a specific mapping, including its right-hand side (rhs), use maparg()For instance, :echo maparg('<Leader>f', 'n') will return a dictionary containing information about the <Leader>f mapping in Normal mode.
  • Using the WhichKey plugin:
    • Plugins like folke/which-key.nvim provide a visual way to explore keymaps. As you type a key sequence, a popup appears showing the available mappings that start with those keys, making it easy to discover what a key is bound to.
These methods provide comprehensive ways to inspect and understand key bindings within your Neovim environment.

2025年7月24日 星期四

To Be Study : Neovim debug

 In Neovim, if a warning or error message appears, more detailed information can be obtained through several methods:

  • Viewing Diagnostic Messages:
    • Floating Window: When the cursor is on a line with a diagnostic message (error, warning, etc.), executing :lua vim.diagnostic.open_float() will open a floating window displaying the full diagnostic message. This function can be mapped to a keybinding for convenience (e.g., <leader>cd in LazyVim).
    • Trouble.nvim: Plugins like Trouble.nvim provide a dedicated horizontal pane at the bottom of the screen to list and navigate through all diagnostic messages, offering a comprehensive overview.
  • Accessing Neovim's Internal Logs:
    • Neovim generates logs that can contain detailed information about errors, warnings, and other events. These logs are typically located in $HOME/.cache/nvim/log on Linux/macOS or C:\Users\profile_name\AppData\Local\nvim-data\log on Windows.
    • The exact path can be found by running :echo stdpath("log") within Neovim.
    • These log files can be opened and examined with a text editor to find more context for specific issues.
  • Checking Recent Messages:
    • The :messages command in Neovim displays a list of recent messages, including error and warning messages that might have appeared and then cleared from the status line.
    • If a specific error message includes an ID (e.g., E72), using :help E72 can provide documentation related to that specific error.
  • Language Server Logs:
    • If the warning or error originates from a Language Server Protocol (LSP) server (e.g., clangdtsserver), these servers often generate their own detailed logs. The location and configuration for these logs are typically specific to each language server and can be found in their respective documentation.

2025年4月1日 星期二

Use GRPC with grpc gateway

 1. Have a proto

2. Generate by protoc

3. use go module + proto package as import path


2025年1月27日 星期一

NVIM handbook

LSP document : https://neovim.io/doc/user/lsp.html

Bolck fold document : https://neovim.io/doc/user/fold.html

Regular expression pattern : https://neovim.io/doc/user/pattern.html

Lazyvim : https://www.lazyvim.org/configuration/lazy.nvim


 1. init.lua

if not use init.lua but use init.vim, try add

lua require("init") 

in init.vim file

2. Install font

https://www.nerdfonts.com/font-downloads

After download, install, and select font with "mono"

3. Change window size 

Use ctrl + <-, ->

There are several window commands that allow you to do this:

  • Ctrl+W +/-: increase/decrease height (ex. 20<C-w>+)
  • Ctrl+W >/<: increase/decrease width (ex. 30<C-w><)
  • Ctrl+W _: set height (ex. 50<C-w>_)
  • Ctrl+W |: set width (ex. 50<C-w>|)
  • Ctrl+W =: equalize width and height of all windows

See also: :help CTRL-W

https://vi.stackexchange.com/questions/514/how-do-i-change-the-current-splits-width-and-height

3.a. Block collapse/fold/open

https://neovim.io/doc/user/fold.html

Fold : zc

Open : zo

...

4. Change window

User 

ctrl + h,j,k,l

or

c + ww

5. Show hidden file in tree

H ( shift + h )

6. switch tab ( edit buffer ) in edit view

H, L (shift + h / shift + l)

7.  handle buffer

space + b + ...

8. install lsp

:LazyExtras

press 'x' to enable plugin lsp

one can use '/' to search, for example : /lang.go search for golang

9. Nevigate

g : show go to menu

gd : goto definition

gD : goto declaration

gc : comment lines

^o : back

9: #j : go to relative j line , #k : go to k relative line above

10 : >> : ident right, << : ident left 

11 : " ff" find in files , " fF" find in file of pwd

12 : ":Telescope live_grep" life grep

13 : check plugin function : :checkhealth telescope

14 : check keymap : :verbose map <leader>fg

15 : add live grep keyp map

15.a : reference to lazy/telescope.nvim/README.md, here we can use 
Normal : 
nnoremap <leader>fg <cmd>Telescope live_grep<cr>
Lua :
nnoremap <leader>fg <cmd>lua require('telescope.builtin').live_grep()<cr>

15.b : modify lazy/LazyVim/lua/lazyvim/plugins/extras/editor/telescope.lua, add a line
{ "<leader>fG", "<cmd>Telescope live_grep<cr>", desc = "Telescope live_grep" },

15.c : ^q : you will leave the find result in the split buffer below

15.d : multiple file replace : :cdo %s/xxx/yyy/gc

15.e : map "current cursor text" to search
{ "<leader>fs", "<cmd>Telescope grep_string<cr>", desc = "Telescope grep_string" },


16. Debug golang

To use nvim debug golang, we need 

1. delve

2. dap related modules

2.1 dap-core, nvim-dap, nvim-dap-ui, nvim-dap-go

2.2 after install, use <leader>d will enter debug mode

17. Grep string under cursor

      { "<leader>sw", LazyVim.pick("grep_string", { word_match = "-w" }), desc = "Word (Root Dir)" },

      { "<leader>sW", LazyVim.pick("grep_string", { root = false, word_match = "-w" }), desc = "Word (cwd)" },

      { "<leader>sw", LazyVim.pick("grep_string"), mode = "v", desc = "Selection (Root Dir)" },

      { "<leader>sW", LazyVim.pick("grep_string", { root = false }), mode = "v", desc = "Selection (cwd)" },

      { "<leader>uC", LazyVim.pick("colorscheme", { enable_preview = true }), desc = "Colorscheme with Preview" },


diff --git a/lua/lazyvim/plugins/extras/editor/telescope.lua b/lua/lazyvim/plugins/extras/editor/telescope.lua

index 55ccace..0806788 100644

--- a/lua/lazyvim/plugins/extras/editor/telescope.lua

+++ b/lua/lazyvim/plugins/extras/editor/telescope.lua

@@ -108,6 +108,8 @@ return {

       { "<leader>ff", LazyVim.pick("files"), desc = "Find Files (Root Dir)" },

       { "<leader>fF", LazyVim.pick("files", { root = false }), desc = "Find Files (cwd)" },

       { "<leader>fg", "<cmd>Telescope git_files<cr>", desc = "Find Files (git-files)" },

+      { "<leader>fG", "<cmd>Telescope live_grep<cr>", desc = "Telescope live_grep" },

+      { "<leader>fs", "<cmd>Telescope grep_string<cr>", desc = "Telescope grep_string" },

       { "<leader>fr", "<cmd>Telescope oldfiles<cr>", desc = "Recent" },

       { "<leader>fR", LazyVim.pick("oldfiles", { cwd = vim.uv.cwd() }), desc = "Recent (cwd)" },

       -- git

17. Formating

Json : :%!jq '.' , https://codegoalie.com/posts/format-json-nvim-jq/


18. Use ctags : golang

ctags -R --languages=Go .


19. Add a plugin

a. path is ~/.config/nvim/lua/plugins

b. put xxx.lua under it

c. example

-- since this is just an example spec, don't actually load anything here and return an empty spec

-- stylua: ignore

if true then return {} end


-- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim

--

-- In your plugin files, you can:

-- * add extra plugins

-- * disable/enabled LazyVim plugins

-- * override the configuration of LazyVim plugins

return {

  -- add gruvbox

  { "ellisonleao/gruvbox.nvim" },


  -- Configure LazyVim to load gruvbox

  {

    "LazyVim/LazyVim",

    opts = {

      colorscheme = "gruvbox",

    },

  },


  -- change trouble config

  {

    "folke/trouble.nvim",

    -- opts will be merged with the parent spec

    opts = { use_diagnostic_signs = true },

  },


  -- disable trouble

  { "folke/trouble.nvim", enabled = false },


  -- override nvim-cmp and add cmp-emoji

  {

    "hrsh7th/nvim-cmp",

    dependencies = { "hrsh7th/cmp-emoji" },

    ---@param opts cmp.ConfigSchema

    opts = function(_, opts)

      table.insert(opts.sources, { name = "emoji" })

    end,

  },


  -- change some telescope options and a keymap to browse plugin files

  {

    "nvim-telescope/telescope.nvim",

    keys = {

      -- add a keymap to browse plugin files

      -- stylua: ignore

      {

        "<leader>fp",

        function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end,

        desc = "Find Plugin File",

      },

    },

    -- change some options

    opts = {

      defaults = {

        layout_strategy = "horizontal",

        layout_config = { prompt_position = "top" },

        sorting_strategy = "ascending",

        winblend = 0,

      },

    },

  },


  -- add pyright to lspconfig

  {

    "neovim/nvim-lspconfig",

    ---@class PluginLspOpts

    opts = {

      ---@type lspconfig.options

      servers = {

        -- pyright will be automatically installed with mason and loaded with lspconfig

        pyright = {},

      },

    },

  },


  -- add tsserver and setup with typescript.nvim instead of lspconfig

  {

    "neovim/nvim-lspconfig",

    dependencies = {

      "jose-elias-alvarez/typescript.nvim",

      init = function()

        require("lazyvim.util").lsp.on_attach(function(_, buffer)

          -- stylua: ignore

          vim.keymap.set( "n", "<leader>co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" })

          vim.keymap.set("n", "<leader>cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer })

        end)

      end,

    },

    ---@class PluginLspOpts

    opts = {

      ---@type lspconfig.options

      servers = {

        -- tsserver will be automatically installed with mason and loaded with lspconfig

        tsserver = {},

      },

      -- you can do any additional lsp server setup here

      -- return true if you don't want this server to be setup with lspconfig

      ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>

      setup = {

        -- example to setup with typescript.nvim

        tsserver = function(_, opts)

          require("typescript").setup({ server = opts })

          return true

        end,

        -- Specify * to use this function as a fallback for any server

        -- ["*"] = function(server, opts) end,

      },

    },

  },


  -- for typescript, LazyVim also includes extra specs to properly setup lspconfig,

  -- treesitter, mason and typescript.nvim. So instead of the above, you can use:

  { import = "lazyvim.plugins.extras.lang.typescript" },


  -- add more treesitter parsers

  {

    "nvim-treesitter/nvim-treesitter",

    opts = {

      ensure_installed = {

        "bash",

        "html",

        "javascript",

        "json",

        "lua",

        "markdown",

        "markdown_inline",

        "python",

        "query",

        "regex",

        "tsx",

        "typescript",

        "vim",

        "yaml",

      },

    },

  },


  -- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above

  -- would overwrite `ensure_installed` with the new value.

  -- If you'd rather extend the default config, use the code below instead:

  {

    "nvim-treesitter/nvim-treesitter",

    opts = function(_, opts)

      -- add tsx and treesitter

      vim.list_extend(opts.ensure_installed, {

        "tsx",

        "typescript",

      })

    end,

  },


  -- the opts function can also be used to change the default opts:

  {

    "nvim-lualine/lualine.nvim",

    event = "VeryLazy",

    opts = function(_, opts)

      table.insert(opts.sections.lualine_x, {

        function()

          return "😄"

        end,

      })

    end,

  },


  -- or you can return new options to override all the defaults

  {

    "nvim-lualine/lualine.nvim",

    event = "VeryLazy",

    opts = function()

      return {

        --[[add your custom lualine config here]]

      }

    end,

  },


  -- use mini.starter instead of alpha

  { import = "lazyvim.plugins.extras.ui.mini-starter" },


  -- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc

  { import = "lazyvim.plugins.extras.lang.json" },


  -- add any tools you want to have installed below

  {

    "williamboman/mason.nvim",

    opts = {

      ensure_installed = {

        "stylua",

        "shellcheck",

        "shfmt",

        "flake8",

      },

    },

  },

}

d. to disable a plugin, add the following

if true then

  return {}

end

20 : After update nvim packages 

        a. Example : Lazy with U or LazyExtras

        b. Example : update node version

        c. Example : update golang version

        What will happen : some package need update

              1. gopls : go install golang.org/x/tools/gopls@latest

              2. mason update : :MasonUpdate

              3. :MasonInstall gopls

21 : Code trace for search function : <leader>-/

I'll help you find how `<leader>-/` is defined in your Neovim configuration and which function it calls. Let me search through your configuration files. 


Searched codebase for "leader / keymap mapping toggle comment", 16 results


Let me search more specifically for the `<leader>/` keymap pattern: 


Searched for text `<leader>/`, 12 results


Great! Now let me look at the LazyVim core configuration files to understand which picker is being used by default: 


Read [](file:///Users/holmaschen/.local/share/nvim/lazy/LazyVim/lua/lazyvim/plugins/extras/editor/snacks_picker.lua)


Now let me check the LazyVim configuration to see which picker is being used and examine the `LazyVim.pick()` function: 


Searched for text `LazyVim.pick` (`**/lazy/LazyVim/lua/**`), 20 results


Let me examine the core LazyVim pick utility module: 


Searched for text `LazyVim.pick` (`**/lazy/LazyVim/lua/lazyvim/util/**`), 4 results


Read [](file:///Users/holmaschen/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/pick.lua)


Now let me check which picker is currently active in your LazyVim setup. Let me look for plugin configuration files that might define which picker is loaded: 


Searched for files matching `**/init.lua`, 10 matches


Let me look for your Neovim configuration outside the lazy plugin directory: 


Read [](file:///Users/holmaschen/.local/share/nvim)


Let me check your Neovim config directory (typically in `~/.config/nvim`): 


Searched for files matching `**/~/.config/nvim/**`, no matches


Ran terminal command: find ~ -name "nvim" -type d 2>/dev/null | head -5


Let me check your actual Neovim configuration: 


Read [](file:///Users/holmaschen/.config/nvim)


Let me check what picker is currently active by looking for any loaded configurations or running a Neovim command: 


Ran terminal command: nvim --headless -c "lua if LazyVim and LazyVim.pick and LazyVim.pick.picker then print(LazyVim.pick.picker.name) else print('LazyVim not loaded') end" +q 2>/dev/null || echo "Could not determine picker"


Let me check what is likely configured by looking at your loaded plugins: 


Searched codebase for "telescope installed configured keymap picker settings", 26 results


Based on my search through your Neovim configuration, I can now explain how `<leader>/` is defined and which function it calls.


## How `<leader>/` is defined


The `<leader>/` keymap is defined in different ways depending on which picker plugin is active in your LazyVim configuration. Looking at your setup, there are three possible picker plugins that could be active:


1. **Snacks Picker** (most likely)

2. **Telescope**

3. **FZF-lua**


## Current Implementation


Based on the search results, your configuration appears to be using **Snacks Picker** (the default for LazyVim). Here's how `<leader>/` is defined:


In snacks_picker.lua, line 60:


```lua

{ "<leader>/", LazyVim.pick("grep"), desc = "Grep (Root Dir)" },

```


## Function Call Chain


When you press `<leader>/`, the following function chain is executed:


1. **`LazyVim.pick("grep")`** - This is a wrapper function from pick.lua


2. **`LazyVim.pick.wrap("grep", opts)`** - Returns a function that calls:


3. **`LazyVim.pick.open("grep", opts)`** - Which translates the command and calls:


4. **`M.picker.open(command, opts)`** - Where `M.picker` is the registered picker (Snacks)


5. **`Snacks.picker.pick("grep", opts)`** - The final function that opens the grep interface


## Specific Function Called


The ultimate function that gets called is:


```lua

Snacks.picker.pick("grep", opts)

```


This opens the Snacks picker in grep mode, allowing you to search for text across all files in your project's root directory.


## Alternative Implementations


If you were using different pickers, the keymap would resolve to:


- **Telescope**: `require("telescope.builtin").live_grep(opts)`

- **FZF-lua**: `require("fzf-lua").live_grep(opts)`


The beauty of LazyVim's picker abstraction is that `<leader>/` always provides the same functionality (project-wide text search) regardless of which picker backend you're using, but the underlying implementation changes based on your configuration.



Let me examine how `Snacks.picker.pick("grep", opts)` actually works by looking into the Snacks.nvim source code. 


Read [](file:///Users/holmaschen/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/init.lua)


Now let me look at the grep source implementation: 


Searched codebase for "grep source snacks picker implementation command rg ag ripgrep", 22 results


Now let me look at the actual grep source file to understand the command it uses: 


Read [](file:///Users/holmaschen/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/source/grep.lua)


Now let me also check the proc source to understand how the command execution works: 


Read [](file:///Users/holmaschen/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/source/proc.lua)


Perfect! Now I have a complete understanding of how `Snacks.picker.pick("grep", opts)` works. Let me provide you with the detailed explanation.


## How `Snacks.picker.pick("grep", opts)` Actually Works


### 1. Command Used: **Ripgrep (`rg`)**


When you call `Snacks.picker.pick("grep", opts)`, it **uses `rg` (ripgrep)** as the underlying command, NOT `ag`, `grep`, or other tools. This is hardcoded in the source file:


```lua

local function get_cmd(opts, filter)

  local cmd = "rg"  -- Hardcoded to use ripgrep

  -- ... rest of the function

end

```


### 2. Command Arguments


The default `rg` command that gets executed looks like this:


```bash

rg --color=never --no-heading --with-filename --line-number --column --smart-case --max-columns=500 --max-columns-preview -g !.git -- "search_pattern"

```


### 3. How It Works Internally


Here's the complete flow:


1. **`LazyVim.pick("grep")`** → calls **`Snacks.picker.pick("grep", opts)`**


2. **Snacks picker** loads the **grep source** from `/snacks/picker/source/grep.lua`


3. **`get_cmd()` function** builds the ripgrep command with these default arguments:

   ```lua

   local args = {

     "--color=never",       -- No colored output

     "--no-heading",        -- Don't group matches by file

     "--with-filename",     -- Include filename in output

     "--line-number",       -- Include line numbers

     "--column",           -- Include column numbers

     "--smart-case",       -- Smart case matching

     "--max-columns=500",  -- Limit column width

     "--max-columns-preview",

     "-g", "!.git",       -- Exclude .git directory

   }

   ```


4. **Additional options** are dynamically added based on your configuration:

   - `--hidden` or `--no-hidden` (show hidden files)

   - `--no-ignore` (show ignored files)

   - `-L` (follow symlinks)

   - `-t <filetype>` (filter by file type)

   - `--fixed-strings` (literal search instead of regex)

   - `-g <glob>` (glob patterns)


5. **Process execution**: The command is executed via proc.lua using Neovim's `uv.spawn()` (libuv process spawning)


6. **Real-time output processing**: Results are streamed live as ripgrep finds matches, parsed, and displayed in the picker interface


### 4. Output Processing


The ripgrep output is parsed in real-time:


```lua

-- Example ripgrep output: "file.lua:123:45:some matching text"

local file, line, col, text = item.text:match("^(.+):(%d+):(%d+):(.*)$")

```


Each result is transformed into a structured item with:

- `file`: The file path

- `pos`: Line and column position `[line, col]`

- `line`: The matching text content


### 5. Why Ripgrep?


Snacks picker uses `rg` because it's:

- **Extremely fast** - faster than `ag` and traditional `grep`

- **Feature-rich** - supports smart case, file type filtering, glob patterns

- **Modern** - handles Unicode, respects `.gitignore` by default

- **Reliable** - well-maintained and widely adopted


### 6. No Fallback


Unlike some other tools, Snacks picker **only** uses ripgrep for grep functionality. There's no fallback to `ag`, `grep`, or other search tools. If `rg` is not available, the grep function would fail.


So to directly answer your question: **`Snacks.picker.pick("grep", opts)` calls the `rg` (ripgrep) command**, not `ag`, `grep`, or any other search tool.