Home

Awesome

๐ŸŒฒ ecolog.nvim (Alpha)

<div align="center">

Neovim Lua

Ecolog (ัะบะพะปะพะณ) - your environment guardian in Neovim. Named after the Russian word for "environmentalist", this plugin protects and manages your environment variables with the same care an ecologist shows for nature.

A Neovim plugin for seamless environment variable integration and management. Provides intelligent autocompletion, type checking, and value peeking for environment variables in your projects. All in one place.

</div>

Table of Contents

๐Ÿ“ฆ Installation

Using lazy.nvim:

Plugin Setup

{
  'philosofonusus/ecolog.nvim',
  dependencies = {
    'hrsh7th/nvim-cmp', -- Optional: for autocompletion support (recommended)
  },
  -- Optional: you can add some keybindings
  -- (I personally use lspsaga so check out lspsaga integration or lsp integration for a smoother experience without separate keybindings)
  keys = {
    { '<leader>ge', '<cmd>EcologGoto<cr>', desc = 'Go to env file' },
    { '<leader>ep', '<cmd>EcologPeek<cr>', desc = 'Ecolog peek variable' },
    { '<leader>es', '<cmd>EcologSelect<cr>', desc = 'Switch env file' },
  },
  -- Lazy loading is done internally
  lazy = false,
  opts = {
    integrations = {
        -- WARNING: for both cmp integrations see readme section below
        nvim_cmp = true, -- If you dont plan to use nvim_cmp set to false, enabled by default
        -- If you are planning to use blink cmp uncomment this line
        -- blink_cmp = true,
    },
    -- Enables shelter mode for sensitive values
    shelter = {
        configuration = {
            partial_mode = false, -- false by default, disables partial mode, for more control check out shelter partial mode
            mask_char = "*",   -- Character used for masking
        },
        modules = {
            cmp = true,       -- Mask values in completion
            peek = false,      -- Mask values in peek view
            files = false,     -- Mask values in files
            telescope = false  -- Mask values in telescope
        }
    },
    -- true by default, enables built-in types (database_url, url, etc.)
    types = true,
    path = vim.fn.getcwd(), -- Path to search for .env files
    preferred_environment = "development", -- Optional: prioritize specific env files
  },
}

Setup auto-completion with nvim-cmp:

require('cmp').setup({
  sources = {
    { name = 'ecolog' },
    -- your other sources...
  },

If you use blink.cmp see Blink-cmp Integration guide

โœจ Features

๐Ÿ” Environment Variable Peeking

๐Ÿค– Smart Autocompletion

๐Ÿ›ก๏ธ Shelter Mode Protection

๐Ÿ”„ Real-time Updates

๐Ÿ“ Multi-Environment Support

๐Ÿ’ก Intelligent Type System

๐Ÿš€ Usage

Available Commands

CommandDescription
:EcologPeek [variable_name]Peek at environment variable value and metadata
:EcologPeekPeek at environment variable under cursor
:EcologRefreshRefresh environment variable cache
:EcologSelectOpen a selection window to choose environment file
:EcologGotoOpen selected environment file in buffer
:EcologGotoVarGo to specific variable definition in env file
:EcologGotoVar [variable_name]Go to specific variable definition in env file with variable under cursor
:EcologShelterToggle [command] [feature]Control shelter mode for masking sensitive values
:EcologShelterLinePeekTemporarily reveal value on current line in env file
:EcologPresetsOpen the preset management UI
:EcologPresetCreate <name>Create a preset from current env file
:EcologPresetValidate <name>Validate current env file against a preset
:Telescope ecolog envAlternative way to open Telescope picker

๐Ÿ“ Environment File Priority

Files are loaded in the following priority order:

  1. .env.{preferred_environment} (if preferred_environment is set)
  2. .env
  3. Other .env.* files (alphabetically)

๐Ÿ”Œ Shell Variables Integration

Ecolog can load environment variables directly from your shell environment. This is useful when you want to:

Basic Usage

Enable shell variable loading with default settings:

require('ecolog').setup({
  load_shell = true
})

Advanced Configuration

For more control over shell variable handling:

require('ecolog').setup({
  load_shell = {
    enabled = true,     -- Enable shell variable loading
    override = false,   -- When false, .env files take precedence over shell variables
    -- Optional: filter specific shell variables
    filter = function(key, value)
      -- Example: only load specific variables
      return key:match("^(PATH|HOME|USER)$") ~= nil
    end,
    -- Optional: transform shell variables before loading
    transform = function(key, value)
      -- Example: prefix shell variables for clarity
      return "[shell] " .. value
    end
  }
})

Configuration Options

OptionTypeDefaultDescription
enabledbooleanfalseEnable/disable shell variable loading
overridebooleanfalseWhen true, shell variables take precedence over .env files
filterfunction|nilnilOptional function to filter which shell variables to load
transformfunction|nilnilOptional function to transform shell variable values

Features

Best Practices

  1. Use filter to limit which shell variables are loaded to avoid cluttering
  2. Consider using transform to clearly mark shell-sourced variables
  3. Be mindful of the override setting when working with both shell and .env variables
  4. Apply shelter mode settings to shell variables containing sensitive data

๐Ÿ’ก Integrations

Nvim-cmp Integration

Add ecolog to your nvim-cmp sources:

require('cmp').setup({
  sources = {
    { name = 'ecolog' },
    -- your other sources...
  },

})

Nvim-cmp integration is enabled by default. To disable it:

require('ecolog').setup({
  integrations = {
    nvim_cmp = false,
  },
})

Blink-cmp Integration

PS: When blink_cmp is enabled, nvim_cmp is disabled by default.

Ecolog provides an integration with blink.cmp for environment variable completions. To enable it:

  1. Enable the integration in your Ecolog setup:
require('ecolog').setup({
  integrations = {
    blink_cmp = true,
  },
})
  1. Configure Blink CMP to use the Ecolog source:
{
  "saghen/blink.cmp",
  opts = {
    sources = {
      completion = {
        enabled_providers = { 'ecolog', 'lsp', 'path', 'snippets', 'buffer' },
      },
      providers = {
        ecolog = { name = 'ecolog', module = 'ecolog.integrations.cmp.blink_cmp' },
      },
    },
  },
}

LSP Integration (Experimental)

โš ๏ธ Warning: The LSP integration is currently experimental and may interfere with your existing LSP setup. Use with caution.

Ecolog provides optional LSP integration that enhances the hover and definition functionality for environment variables. When enabled, it will:

meaning you dont need any custom keymaps

Setup

To enable LSP integration, add this to your Neovim configuration:

require('ecolog').setup({
    integrations = {
        lsp = true,
    }
})

PS: If you're using lspsaga, please see section LSP Saga Integration don't use lsp integration use one or the other.

Features

Known Limitations

  1. The integration overrides the default LSP hover and definition handlers
  2. May conflict with other plugins that modify LSP hover behavior
  3. Performance impact on LSP operations (though optimized and should be unnoticable)

Disabling LSP Integration

If you experience any issues, you can disable the LSP integration:

require('ecolog').setup({
    integrations = {
        lsp = false,
    }
})

Please report such issues on our GitHub repository

LSP Saga Integration

Ecolog provides integration with lspsaga.nvim that enhances hover and goto-definition functionality for environment variables while preserving Saga's features for other code elements.

Setup

To enable LSP Saga integration, add this to your configuration:

require('ecolog').setup({
    integrations = {
        lspsaga = true,
    }
})

PS: If you're using lspsaga then don't use lsp integration use one or the other.

Features

The integration adds two commands that intelligently handle both environment variables and regular code:

  1. EcologSagaHover:

    • Shows environment variable value when hovering over env vars
    • Falls back to Saga's hover for other code elements
    • Automatically replaces existing Saga hover keymaps
  2. EcologSagaGD (Goto Definition):

    • Jumps to environment variable definition in .env file
    • Uses Saga's goto definition for other code elements
    • Automatically replaces existing Saga goto-definition keymaps

๐Ÿ’ก Note: When enabled, the integration automatically detects and updates your existing Lspsaga keymaps to use Ecolog's enhanced functionality. No manual keymap configuration required!

Example Configuration

{
  'philosofonusus/ecolog.nvim',
  dependencies = {
    'nvimdev/lspsaga.nvim',
    'hrsh7th/nvim-cmp',
  },
  opts = {
    integrations = {
      lspsaga = true,
    }
  },
}

๐Ÿ’ก Note: The LSP Saga integration provides a smoother experience than the experimental LSP integration if you're already using Saga in your setup.

Telescope Integration

First, load the extension:

require('telescope').load_extension('ecolog')

Then configure it in your Telescope setup (optional):

require('telescope').setup({
  extensions = {
    ecolog = {
      shelter = {
        -- Whether to show masked values when copying to clipboard
        mask_on_copy = false,
      },
      -- Default keybindings
      mappings = {
        -- Key to copy value to clipboard
        copy_value = "<C-y>",
        -- Key to copy name to clipboard
        copy_name = "<C-n>",
        -- Key to append value to buffer
        append_value = "<C-a>",
        -- Key to append name to buffer (defaults to <CR>)
        append_name = "<CR>",
      },
    }
  }
})

๐Ÿ”ง Language Support

๐ŸŸข Currently Supported and Tested

LanguageEnvironment Access & Autocompletion triggerDescription
Javascript/TypeScript/Reactimport.meta.env['*<br>process.env[*'<br>import.meta.env["*<br>process.env[*"Full support for Node.js, Vite environment variables
JavaScript/Typescript/Reactprocess.env.*<br>import.meta.env.*Complete support for both types of annotations
DenoDeno.env.get("*<br>Deno.env.get('Deno runtime environment variable access
BunBun.env.*<br>Bun.env["*<br>Bun.env['Bun runtime environment variable access
Pythonos.environ.get('*<br>os.environ['*<br>os.environ["*Native Python environment variable access
Luaos.getenv("*<br>os.getenv('*Native Lua environment variable access

๐Ÿ”ด Supported but Not Thoroughly Tested (may be broken)

LanguageEnvironment Access & Autocompletion triggerDescription
PHPgetenv()<br>_ENV[]Support for both modern and legacy PHP env access
Goos.Getenv("*Go standard library environment access
Ruststd::env::var()<br>env::var()Rust standard library environment access

๐Ÿšง Coming Soon

LanguagePlanned SupportStatus
C#Environment.GetEnvironmentVariable()Planned
Shell$VAR, ${VAR}Planned
RubyENV[]<br>ENV.fetch()Planned
DockerARG *<br>ENV *<br>${*Planned

๐Ÿ’ก Want support for another language?
Feel free to contribute by adding a new provider! Or just check out the Custom Providers section.

๐Ÿ”Œ Custom Providers

You can add support for additional languages by registering custom providers. Each provider defines how environment variables are detected and extracted in specific file types.

Example: Adding Ruby Support

require('ecolog').setup({
  providers = {
    {
      -- Pattern to match environment variable access
      pattern = "ENV%[['\"]%w['\"]%]",
      -- Filetype(s) this provider supports (string or table)
      filetype = "ruby",
      -- Function to extract variable name from the line
      extract_var = function(line, col)
        local before_cursor = line:sub(1, col + 1)
        return before_cursor:match("ENV%['\"['\"]%]$")
      end,
      -- Function to return completion trigger pattern
      get_completion_trigger = function()
        return "ENV['"
      end
    }
  }
})

๐Ÿ›ก๏ธ Shelter Mode

Shelter mode provides a secure way to work with sensitive environment variables by masking their values in different contexts. This feature helps prevent accidental exposure of sensitive data like API keys, passwords, tokens, and other credentials.

๐Ÿ”ง Configuration

require('ecolog').setup({
    shelter = {
        configuration = {
            -- Partial mode configuration:
            -- false: completely mask values (default)
            -- true: use default partial masking settings
            -- table: customize partial masking
            -- partial_mode = false,
            -- or with custom settings:
            partial_mode = {
                show_start = 3,    -- Show first 3 characters
                show_end = 3,      -- Show last 3 characters
                min_mask = 3,      -- Minimum masked characters
            },
            mask_char = "*",   -- Character used for masking
        },
        modules = {
            cmp = false,       -- Mask values in completion
            peek = false,      -- Mask values in peek view
            files = false,     -- Mask values in files
            telescope = false  -- Mask values in telescope
        }
    },
    path = vim.fn.getcwd(), -- Path to search for .env files
    preferred_environment = "development", -- Optional: prioritize specific env files
})

๐ŸŽฏ Features

Partial Masking

Three modes of operation:

  1. Full Masking (Default)

    partial_mode = false
    -- Example: "my-secret-key" -> "************"
    
  2. Default Partial Masking

    partial_mode = true
    -- Example: "my-secret-key" -> "my-***-key"
    
  3. Custom Partial Masking

    partial_mode = {
        show_start = 4,    -- Show more start characters
        show_end = 2,      -- Show fewer end characters
        min_mask = 3,      -- Minimum mask length
    }
    -- Example: "my-secret-key" -> "my-s***ey"
    

1. Completion Protection (cmp)

2. Peek Window Protection

3. File Content Protection

๐ŸŽฎ Commands

:EcologShelterToggle provides flexible control over shelter mode:

  1. Basic Usage:

    :EcologShelterToggle              " Toggle between all-off and initial settings
    
  2. Global Control:

    :EcologShelterToggle enable       " Enable all shelter modes
    :EcologShelterToggle disable      " Disable all shelter modes
    
  3. Feature-Specific Control:

    :EcologShelterToggle enable cmp   " Enable shelter for completion only
    :EcologShelterToggle disable peek " Disable shelter for peek only
    :EcologShelterToggle enable files " Enable shelter for file display
    
  4. Quick Value Reveal:

    :EcologShelterLinePeek           " Temporarily reveal value on current line
    
    • Shows the actual value for the current line
    • Value is hidden again when cursor moves away
    • Only works when shelter mode is enabled for files

๐Ÿ“ Example

Original .env file:

# Authentication
JWT_SECRET=my-super-secret-key
AUTH_TOKEN="bearer 1234567890"

# Database Configuration
DB_HOST=localhost
DB_USER=admin
DB_PASS=secure_password123

With full masking (partial_mode = false):

# Authentication
JWT_SECRET=********************
AUTH_TOKEN=******************

# Database Configuration
DB_HOST=*********
DB_USER=*****
DB_PASS=******************

Partial Masking Examples

With default settings (show_start=3, show_end=3, min_mask=3):

"mysecretkey"     -> "mys***key"    # Enough space for min_mask (3) characters
"secret"          -> "******"        # Not enough space for min_mask between shown parts
"api_key"         -> "*******"       # Would only have 1 char for masking, less than min_mask
"very_long_key"   -> "ver*****key"   # Plenty of space for masking

The min_mask setting ensures that sensitive values are properly protected by requiring a minimum number of masked characters between the visible parts. If this minimum cannot be met, the entire value is masked for security.

Telescope Integration

The plugin provides a Telescope extension for searching and managing environment variables.

Usage

Open the environment variables picker:

:Telescope ecolog env

Features

Default Keymaps

KeyAction
<CR>Insert variable name
<C-y>Copy value to clipboard
<C-n>Copy name to clipboard
<C-a>Append value to buffer

All keymaps are customizable through the configuration.

๐Ÿ›ก Ecolog Types

Ecolog includes a flexible type system for environment variables with built-in and custom types.

Type Configuration

Configure types through the types option in setup:

require('ecolog').setup({
  custom_types = {
      semver = {
        pattern = "^v?%d+%.%d+%.%d+%-?[%w]*$",
        validate = function(value)
          local major, minor, patch = value:match("^v?(%d+)%.(%d+)%.(%d+)")
          return major and minor and patch
        end,
      },
     aws_region = {
      pattern = "^[a-z]{2}%-[a-z]+%-[0-9]$",
      validate = function(value)
        local valid_regions = {
          ["us-east-1"] = true,
          ["us-west-2"] = true,
          -- ... etc
        }
        return valid_regions[value] == true
      end
    }
  },
  types = {
    -- Built-in types
    url = true,          -- URLs (http/https)
    localhost = true,    -- Localhost URLs
    ipv4 = true,        -- IPv4 addresses
    database_url = true, -- Database connection strings
    number = true,       -- Integers and decimals
    boolean = true,      -- true/false/yes/no/1/0
    json = true,         -- JSON objects and arrays
    iso_date = true,     -- ISO 8601 dates (YYYY-MM-DD)
    iso_time = true,     -- ISO 8601 times (HH:MM:SS)
    hex_color = true,    -- Hex color codes (#RGB or #RRGGBB)
  }
})

You can also:

require('ecolog').setup({
  custom_types = {
    jwt = {
      pattern = "^[A-Za-z0-9%-_]+%.[A-Za-z0-9%-_]+%.[A-Za-z0-9%-_]+$",
      validate = function(value)
        local parts = vim.split(value, ".", { plain = true })
        return #parts == 3
      end
    },
  }
  types = {
    url = true,
    number = true,
  }
})

Custom Type Definition

Each custom type requires:

  1. pattern (required): A Lua pattern string for initial matching
  2. validate (optional): A function for additional validation
  3. transform (optional): A function to transform the value

Example usage in .env files:

VERSION=v1.2.3                  # Will be detected as semver type
REGION=us-east-1               # Will be detected as aws_region type
AUTH_TOKEN=eyJhbG.eyJzd.iOiJ  # Will be detected as jwt type

๐Ÿ’ก Environment Presets

Save and validate your environment files against predefined presets. This helps ensure consistency across different environments and team members.

Configuration

The presets module is enabled by default. You can disable it in your configuration:

require('ecolog').setup({
  presets = false -- Disable presets module
})

Preset Management UI

The preset management UI provides an interactive way to manage your environment presets:

List View

Edit View

Presets are stored in ecolog_presets.json in your Neovim config directory and can be shared with your team to ensure consistent environment variables across different environments.

๐Ÿ’ก Tips

  1. Selective Protection: Enable shelter mode only for sensitive environments:

    -- In your config
    if vim.fn.getcwd():match("production") then
      require('ecolog').setup({
        shelter = {
            configuration = {
                partial_mode = {
                    show_start = 3,    -- Number of characters to show at start
                    show_end = 3,      -- Number of characters to show at end
                    min_mask = 3,      -- Minimum number of mask characters
                }
               mask_char = "*",   -- Character used for masking
            },
            modules = {
                cmp = true,       -- Mask values in completion
                peek = true,      -- Mask values in peek view
                files = true,     -- Mask values in files
                telescope = false -- Mask values in telescope
            }
        },
        path = vim.fn.getcwd(), -- Path to search for .env files
        preferred_environment = "development", -- Optional: prioritize specific env files
      })
    end
    
  2. Custom Masking: Use different characters for masking:

    shelter = {
        configuration = {
           mask_char = "โ€ข"  -- Use dots
        }
    }
    -- or
    shelter = {
        configuration = {
           mask_char = "โ–ˆ"  -- Use blocks
        }
    }
    
  3. Temporary Viewing: Use :EcologShelterToggle disable temporarily when you need to view values, then re-enable with :EcologShelterToggle enable

  4. Security Best Practices:

    • Enable shelter mode by default for production environments
    • Use file shelter mode during screen sharing or pair programming
    • Enable completion shelter mode to prevent accidental exposure in screenshots

๐ŸŽจ Theme Integration

The plugin seamlessly integrates with your current colorscheme:

ElementColor Source
Variable namesIdentifier
TypesType
ValuesString
SourcesDirectory

๐Ÿ› ๏ธ Author Setup

It's author's (philosofonusus) personal setup for ecolog.nvim if you don't want to think much of a setup and reading docs:

return {
  {
    'philosofonusus/ecolog.nvim',
    keys = {
      { '<leader>ge', '<cmd>EcologGoto<cr>', desc = 'Go to env file' },
      { '<leader>es', '<cmd>EcologSelect<cr>', desc = 'Switch env file' },
      { '<leader>eS', '<cmd>EcologShelterToggle<cr>', desc = 'Ecolog shelter toggle' },
    },
    dependencies = { 'nvim-telescope/telescope.nvim' },
    lazy = false,
    opts = {
      preferred_environment = 'local',
      types = true,
      integrations = {
        lspsaga = true, -- if you don't use lspsaga replace this line with lsp = true,
      },
      shelter = {
        configuration = {
          partial_mode = true,
          mask_char = '*',
        },
        modules = {
          files = true,
          peek = false,
          telescope = false,
          cmp = true,
        },
      },
      path = vim.fn.getcwd(),
    },
  },
}

๐Ÿค Contributing

Contributions are welcome! Feel free to:

๐Ÿ“„ License

MIT License - See LICENSE for details.


<div align="center"> Made with โค๏ธ by <a href="https://github.com/philosofonusus">TENTACLE</a> </div>