github.com/trans/ignore

Ignore file parser and matcher

3 stars
2 dependents
License: MIT

Nothing has been indexed for 0.4.0 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.

Installation

# Add this to your shard.yml
dependencies:
  ignore:
    github: trans/ignore
    version: ~> 0.4.0

Then run:

shards install

shard.yml

No shard.yml has been indexed for 0.4.0. You can read it on the repository.

Dependencies

Unknown: the shard.yml for this version has not been read yet.

README

This README is the one indexed from the repository at its latest ref, not from the tag for this version.

ignore

A .gitignore compatible pattern parser for Crystal.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      ignore:
        github: trans/ignore
  2. Run shards install

Usage

require "ignore"

# Parse gitignore content
matcher = Ignore.parse(<<-GITIGNORE
  build/
  *.o
  *.log
  !important.log
GITIGNORE
)

matcher.ignores?("build/")       # => true (directory)
matcher.ignores?("main.o")       # => true
matcher.ignores?("debug.log")    # => true
matcher.ignores?("important.log") # => false (negated)

# Quick one-liner
Ignore.ignores?("foo.log", "*.log")  # => true

Directory Matching

Use a trailing slash to check directories:

matcher = Ignore.parse("build/")
matcher.ignores?("build/")  # => true (directory)
matcher.ignores?("build")   # => false (file)

Building Patterns Incrementally

matcher = Ignore::Matcher.new
matcher.add("*.o")
matcher.add("*.log")
matcher.add("!important.log")
matcher.ignores?("test.o")  # => true

# Inspect and manage patterns
matcher.patterns  # => ["*.o", "*.log", "!important.log"]
matcher.size      # => 3
matcher.clear     # remove all patterns

# Enumerable support
matcher.each { |pattern| puts pattern }
matcher.select { |p| p.starts_with?("*") }

Loading from a Directory Tree

Load all .gitignore files from a project, with patterns scoped to their directories:

matcher = Ignore.root("/path/to/project")
matcher.ignores?("src/debug.log")

This loads .gitignore files from the root and all subdirectories. Patterns from deeper directories take precedence, so a !debug.log in src/.gitignore will override *.log in the root .gitignore.

You can also load other ignore file formats:

# Load .dockerignore files
matcher = Ignore.root("/path/to/project", ".dockerignore")

# Load .npmignore files
matcher = Ignore.root("/path/to/project", ".npmignore")

Loading Individual Files

matcher = Ignore::Matcher.new
matcher.add_file(".gitignore")
matcher.add_file("src/.gitignore", base: "src/")

Managing Ignore Files

Use Ignore::File to read, modify, and save ignore files:

file = Ignore::File.new(".gitignore")

# Inspect patterns
file.patterns   # => ["*.log", "build/"]
file.lines      # => ["# Build artifacts", "*.log", "", "build/"]
file.size       # => 2 (pattern count, excludes comments/blanks)

# Modify patterns
file.add("*.tmp")
file.remove("*.log")
file.includes?("*.tmp")  # => true

# Check paths against patterns
file.ignores?("debug.tmp")  # => true

# Save changes (preserves comments and blank lines)
file.save

# Reload from disk (discards unsaved changes)
file.reload

# Enumerable support (iterates over patterns only)
file.each { |pattern| puts pattern }

Filtered Directory Operations

Use Ignore::Dir for filtered directory listings and glob results:

dir = Ignore::Dir.new("/path/to/project", "*.log", "build/")

dir.glob("**/*.cr")           # filtered glob
dir.children                   # filtered directory children
dir.entries                    # filtered entries (includes . and ..)
dir.each_child { |entry| ... } # filtered iteration

# Include hidden files in glob
dir.glob("**/*", match: :dot_files)

# Load patterns from .gitignore files automatically
dir = Ignore::Dir.new("/path/to/project", root: ".gitignore")

# Load from a single ignore file
dir = Ignore::Dir.new("/path/to/project", file: ".gitignore")

Directory patterns like build/ will filter out the directory and all its contents.

Inverse Filtering

Get only the ignored files (useful for cleanup tools):

dir = Ignore::Dir.new("/path/to/project", "*.log", "build/")

dir.ignored_glob("**/*")       # only ignored paths
dir.ignored_children           # only ignored children
dir.ignored_entries            # only ignored entries
dir.each_ignored_child { |e| } # iterate ignored children

Enumerable Support

Ignore::Dir includes Enumerable, iterating over non-ignored children:

dir = Ignore::Dir.new("/path/to/project", "*.log")
dir.select { |entry| entry.ends_with?(".cr") }
dir.map { |entry| entry.upcase }

Dir Monkey Patch (Optional)

For convenience, you can optionally load a monkey patch that adds ignore methods to Dir:

require "ignore/core_ext"

# Class method (uses current directory)
Dir.ignore("*.log", "build/").glob("**/*")
Dir.ignore(root: ".gitignore").glob("**/*")

# Instance method
Dir.new("/path/to/project").ignore("*.log").glob("**/*")
Dir.new("/path/to/project").ignore(root: ".gitignore").children

Supported Patterns

PatternDescription
*.txtWildcard, matches any .txt file
?Single character wildcard
[abc]Character class
[a-z]Character range
[!abc]Negated character class
build/Directory only (trailing slash)
/rootAnchored to root (leading slash)
foo/barAnchored (contains slash)
!patternNegation (un-ignore)
**/fooMatch in all directories
foo/**Match everything inside
a/**/bZero or more directories between
\# \!Escaped special characters

License

MIT