mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
feat: add Perl language rules and update documentation
Add rules/perl/ with 5 rule files (coding-style, testing, patterns, hooks, security) following the same structure as existing languages. Update README.md, README.zh-CN.md, and rules/README.md to document Perl support including badges, directory trees, install instructions, and rule counts.
This commit is contained in:
committed by
Affaan Mustafa
parent
8f87a5408f
commit
ae5c9243c9
@@ -17,7 +17,8 @@ rules/
|
||||
├── typescript/ # TypeScript/JavaScript specific
|
||||
├── python/ # Python specific
|
||||
├── golang/ # Go specific
|
||||
└── swift/ # Swift specific
|
||||
├── swift/ # Swift specific
|
||||
└── perl/ # Perl specific
|
||||
```
|
||||
|
||||
- **common/** contains universal principles — no language-specific code examples.
|
||||
@@ -33,6 +34,7 @@ rules/
|
||||
./install.sh python
|
||||
./install.sh golang
|
||||
./install.sh swift
|
||||
./install.sh perl
|
||||
|
||||
# Install multiple languages at once
|
||||
./install.sh typescript python
|
||||
@@ -55,6 +57,7 @@ cp -r rules/typescript ~/.claude/rules/typescript
|
||||
cp -r rules/python ~/.claude/rules/python
|
||||
cp -r rules/golang ~/.claude/rules/golang
|
||||
cp -r rules/swift ~/.claude/rules/swift
|
||||
cp -r rules/perl ~/.claude/rules/perl
|
||||
|
||||
# Attention ! ! ! Configure according to your actual project requirements; the configuration here is for reference only.
|
||||
```
|
||||
@@ -88,7 +91,7 @@ To add support for a new language (e.g., `rust/`):
|
||||
When language-specific rules and common rules conflict, **language-specific rules take precedence** (specific overrides general). This follows the standard layered configuration pattern (similar to CSS specificity or `.gitignore` precedence).
|
||||
|
||||
- `rules/common/` defines universal defaults applicable to all projects.
|
||||
- `rules/golang/`, `rules/python/`, `rules/typescript/`, etc. override those defaults where language idioms differ.
|
||||
- `rules/golang/`, `rules/python/`, `rules/perl/`, `rules/typescript/`, etc. override those defaults where language idioms differ.
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
46
rules/perl/coding-style.md
Normal file
46
rules/perl/coding-style.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.pl"
|
||||
- "**/*.pm"
|
||||
- "**/*.t"
|
||||
- "**/*.psgi"
|
||||
- "**/*.cgi"
|
||||
---
|
||||
# Perl Coding Style
|
||||
|
||||
> This file extends [common/coding-style.md](../common/coding-style.md) with Perl specific content.
|
||||
|
||||
## Standards
|
||||
|
||||
- Always `use v5.36` (enables `strict`, `warnings`, `say`, subroutine signatures)
|
||||
- Use subroutine signatures — never unpack `@_` manually
|
||||
- Prefer `say` over `print` with explicit newlines
|
||||
|
||||
## Immutability
|
||||
|
||||
- Use **Moo** with `is => 'ro'` and `Types::Standard` for all attributes
|
||||
- Never use blessed hashrefs directly — always use Moo/Moose accessors
|
||||
- **OO override note**: Moo `has` attributes with `builder` or `default` are acceptable for computed read-only values
|
||||
|
||||
## Formatting
|
||||
|
||||
Use **perltidy** with these settings:
|
||||
|
||||
```
|
||||
-i=4 # 4-space indent
|
||||
-l=100 # 100 char line length
|
||||
-ce # cuddled else
|
||||
-bar # opening brace always right
|
||||
```
|
||||
|
||||
## Linting
|
||||
|
||||
Use **perlcritic** at severity 3 with themes: `core`, `pbp`, `security`.
|
||||
|
||||
```bash
|
||||
perlcritic --severity 3 --theme 'core || pbp || security' lib/
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
See skill: `perl-patterns` for comprehensive modern Perl idioms and best practices.
|
||||
22
rules/perl/hooks.md
Normal file
22
rules/perl/hooks.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.pl"
|
||||
- "**/*.pm"
|
||||
- "**/*.t"
|
||||
- "**/*.psgi"
|
||||
- "**/*.cgi"
|
||||
---
|
||||
# Perl Hooks
|
||||
|
||||
> This file extends [common/hooks.md](../common/hooks.md) with Perl specific content.
|
||||
|
||||
## PostToolUse Hooks
|
||||
|
||||
Configure in `~/.claude/settings.json`:
|
||||
|
||||
- **perltidy**: Auto-format `.pl` and `.pm` files after edit
|
||||
- **perlcritic**: Run lint check after editing `.pm` files
|
||||
|
||||
## Warnings
|
||||
|
||||
- Warn about `print` in non-script `.pm` files — use `say` or a logging module (e.g., `Log::Any`)
|
||||
76
rules/perl/patterns.md
Normal file
76
rules/perl/patterns.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.pl"
|
||||
- "**/*.pm"
|
||||
- "**/*.t"
|
||||
- "**/*.psgi"
|
||||
- "**/*.cgi"
|
||||
---
|
||||
# Perl Patterns
|
||||
|
||||
> This file extends [common/patterns.md](../common/patterns.md) with Perl specific content.
|
||||
|
||||
## Repository Pattern
|
||||
|
||||
Use **DBI** or **DBIx::Class** behind an interface:
|
||||
|
||||
```perl
|
||||
package MyApp::Repo::User;
|
||||
use Moo;
|
||||
|
||||
has dbh => (is => 'ro', required => 1);
|
||||
|
||||
sub find_by_id ($self, $id) {
|
||||
my $sth = $self->dbh->prepare('SELECT * FROM users WHERE id = ?');
|
||||
$sth->execute($id);
|
||||
return $sth->fetchrow_hashref;
|
||||
}
|
||||
```
|
||||
|
||||
## DTOs / Value Objects
|
||||
|
||||
Use **Moo** classes with **Types::Standard** (equivalent to Python dataclasses):
|
||||
|
||||
```perl
|
||||
package MyApp::DTO::User;
|
||||
use Moo;
|
||||
use Types::Standard qw(Str Int);
|
||||
|
||||
has name => (is => 'ro', isa => Str, required => 1);
|
||||
has email => (is => 'ro', isa => Str, required => 1);
|
||||
has age => (is => 'ro', isa => Int);
|
||||
```
|
||||
|
||||
## Resource Management
|
||||
|
||||
- Always use **three-arg open** with `autodie`
|
||||
- Use **Path::Tiny** for file operations
|
||||
|
||||
```perl
|
||||
use autodie;
|
||||
use Path::Tiny;
|
||||
|
||||
my $content = path('config.json')->slurp_utf8;
|
||||
```
|
||||
|
||||
## Module Interface
|
||||
|
||||
Use `Exporter 'import'` with `@EXPORT_OK` — never `@EXPORT`:
|
||||
|
||||
```perl
|
||||
use Exporter 'import';
|
||||
our @EXPORT_OK = qw(parse_config validate_input);
|
||||
```
|
||||
|
||||
## Dependency Management
|
||||
|
||||
Use **cpanfile** + **carton** for reproducible installs:
|
||||
|
||||
```bash
|
||||
carton install
|
||||
carton exec prove -lr t/
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
See skill: `perl-patterns` for comprehensive modern Perl patterns and idioms.
|
||||
69
rules/perl/security.md
Normal file
69
rules/perl/security.md
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.pl"
|
||||
- "**/*.pm"
|
||||
- "**/*.t"
|
||||
- "**/*.psgi"
|
||||
- "**/*.cgi"
|
||||
---
|
||||
# Perl Security
|
||||
|
||||
> This file extends [common/security.md](../common/security.md) with Perl specific content.
|
||||
|
||||
## Taint Mode
|
||||
|
||||
- Use `-T` flag on all CGI/web-facing scripts
|
||||
- Sanitize `%ENV` (`$ENV{PATH}`, `$ENV{CDPATH}`, etc.) before any external command
|
||||
|
||||
## Input Validation
|
||||
|
||||
- Use allowlist regex for untainting — never `/(.*)/s`
|
||||
- Validate all user input with explicit patterns:
|
||||
|
||||
```perl
|
||||
if ($input =~ /\A([a-zA-Z0-9_-]+)\z/) {
|
||||
my $clean = $1;
|
||||
}
|
||||
```
|
||||
|
||||
## File I/O
|
||||
|
||||
- **Three-arg open only** — never two-arg open
|
||||
- Prevent path traversal with `Cwd::realpath`:
|
||||
|
||||
```perl
|
||||
use Cwd 'realpath';
|
||||
my $safe_path = realpath($user_path);
|
||||
die "Path traversal" unless $safe_path =~ m{\A/allowed/directory/};
|
||||
```
|
||||
|
||||
## Process Execution
|
||||
|
||||
- Use **list-form `system()`** — never single-string form
|
||||
- Use **IPC::Run3** for capturing output
|
||||
- Never use backticks with variable interpolation
|
||||
|
||||
```perl
|
||||
system('grep', '-r', $pattern, $directory); # safe
|
||||
```
|
||||
|
||||
## SQL Injection Prevention
|
||||
|
||||
Always use DBI placeholders — never interpolate into SQL:
|
||||
|
||||
```perl
|
||||
my $sth = $dbh->prepare('SELECT * FROM users WHERE email = ?');
|
||||
$sth->execute($email);
|
||||
```
|
||||
|
||||
## Security Scanning
|
||||
|
||||
Run **perlcritic** with the security theme at severity 4+:
|
||||
|
||||
```bash
|
||||
perlcritic --severity 4 --theme security lib/
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
See skill: `perl-security` for comprehensive Perl security patterns, taint mode, and safe I/O.
|
||||
54
rules/perl/testing.md
Normal file
54
rules/perl/testing.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.pl"
|
||||
- "**/*.pm"
|
||||
- "**/*.t"
|
||||
- "**/*.psgi"
|
||||
- "**/*.cgi"
|
||||
---
|
||||
# Perl Testing
|
||||
|
||||
> This file extends [common/testing.md](../common/testing.md) with Perl specific content.
|
||||
|
||||
## Framework
|
||||
|
||||
Use **Test2::V0** for new projects (not Test::More):
|
||||
|
||||
```perl
|
||||
use Test2::V0;
|
||||
|
||||
is($result, 42, 'answer is correct');
|
||||
|
||||
done_testing;
|
||||
```
|
||||
|
||||
## Runner
|
||||
|
||||
```bash
|
||||
prove -l t/ # adds lib/ to @INC
|
||||
prove -lr -j8 t/ # recursive, 8 parallel jobs
|
||||
```
|
||||
|
||||
Always use `-l` to ensure `lib/` is on `@INC`.
|
||||
|
||||
## Coverage
|
||||
|
||||
Use **Devel::Cover** — target 80%+:
|
||||
|
||||
```bash
|
||||
cover -test
|
||||
```
|
||||
|
||||
## Mocking
|
||||
|
||||
- **Test::MockModule** — mock methods on existing modules
|
||||
- **Test::MockObject** — create test doubles from scratch
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Always end test files with `done_testing`
|
||||
- Never forget the `-l` flag with `prove`
|
||||
|
||||
## Reference
|
||||
|
||||
See skill: `perl-testing` for detailed Perl TDD patterns with Test2::V0, prove, and Devel::Cover.
|
||||
Reference in New Issue
Block a user