Initial commit
This commit is contained in:
13
.claude-plugin/plugin.json
Normal file
13
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "dotfiles",
|
||||
"description": "My dot files for the AI era.",
|
||||
"version": "0.0.5",
|
||||
"author": {
|
||||
"name": "Mauricio Gomes",
|
||||
"email": "mauricio@edge14.com",
|
||||
"url": "https://mauriciogomes.com"
|
||||
},
|
||||
"skills": [
|
||||
"./skills"
|
||||
]
|
||||
}
|
||||
73
plugin.lock.json
Normal file
73
plugin.lock.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:mgomes/3xo-suit:plugins/dotfiles",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "4e8aded7750737e6a7abf82349fde30950d5a08e",
|
||||
"treeHash": "b1f8f074e24ce037f88ca3d245a9a60a265f293f4f77d15631ed9d2aadc3ac32",
|
||||
"generatedAt": "2025-11-28T10:27:05.148214Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "dotfiles",
|
||||
"description": "My dot files for the AI era.",
|
||||
"version": "0.0.5"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "1e8ee8bf3238d2b1d5a96817bd48902a322c3a5f1366a22b359327fa6065185a"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "a897840131d47cb2af4a8e93acf450fd8a21e927270921f8f6e89a8ac3f4c7b3"
|
||||
},
|
||||
{
|
||||
"path": "skills/summarizing-websites/SKILL.md",
|
||||
"sha256": "d63f88ac63b65cddff6b283d21d12c29577a8a96b2ccd6b274f974714d4ee27f"
|
||||
},
|
||||
{
|
||||
"path": "skills/summarizing-websites/scripts/jina.rb",
|
||||
"sha256": "72a86eafa07e3bd25b890d4c2ad089fced02c4d940a5c0b7a663476524413bb5"
|
||||
},
|
||||
{
|
||||
"path": "skills/programming-go/SKILL.md",
|
||||
"sha256": "9f417a02927ee8474d4742f8fe4b4cc31e98f343b0fbb04ec29c7a2ac2a4fbf6"
|
||||
},
|
||||
{
|
||||
"path": "skills/searching-files/SKILL.md",
|
||||
"sha256": "eb72cb8a0f048587ce20537bde8362b302ddaa25bb2094eb079b133249a45b05"
|
||||
},
|
||||
{
|
||||
"path": "skills/searching-files/reference/linux.md",
|
||||
"sha256": "abc35c5a566679d466d8e8813b558a9b30f9409d9e8d8c16beff467cf22789a5"
|
||||
},
|
||||
{
|
||||
"path": "skills/searching-files/reference/macos.md",
|
||||
"sha256": "4a8547035553fbc4899f7e74d43d0a8eb54277ad114d7879705bc5d6a5fd7b9b"
|
||||
},
|
||||
{
|
||||
"path": "skills/frontend-design/SKILL.md",
|
||||
"sha256": "e952f7a65326eea8301cee4f3b0232f8e34e54b718e5e00c2a7cc320014936c6"
|
||||
},
|
||||
{
|
||||
"path": "skills/programming-ruby/SKILL.md",
|
||||
"sha256": "57bc7632f6b000163ee441209e76c52fb8f1ddc426c3f9f56805016eb1734e7b"
|
||||
}
|
||||
],
|
||||
"dirSha256": "b1f8f074e24ce037f88ca3d245a9a60a265f293f4f77d15631ed9d2aadc3ac32"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
45
skills/frontend-design/SKILL.md
Normal file
45
skills/frontend-design/SKILL.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: frontend-design
|
||||
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
|
||||
license: Complete terms in LICENSE.txt
|
||||
---
|
||||
|
||||
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
|
||||
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
||||
|
||||
## Design Thinking
|
||||
|
||||
Before coding, understand the context and commit to an aesthetic direction:
|
||||
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
||||
|
||||
Then implement working code (HTML/CSS/JS, React, shadcn, etc.) that is:
|
||||
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
|
||||
Focus on:
|
||||
|
||||
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
||||
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
||||
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
||||
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
||||
|
||||
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
||||
|
||||
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
||||
|
||||
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
80
skills/programming-go/SKILL.md
Normal file
80
skills/programming-go/SKILL.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
name: programming-go
|
||||
description: Best practices when developing in Go codebases
|
||||
---
|
||||
|
||||
# Programming Go
|
||||
|
||||
## Instructions
|
||||
|
||||
- Don't use `interface{}` -- use `any` instead
|
||||
|
||||
- Use the "-" tag when Marshalling JSON will cause the field to be omitted. Use this when we have private data on a field that’s meant to be excluded from an API response.
|
||||
|
||||
- Use the Go 1.22 syntax for `for` loops:
|
||||
|
||||
Write this:
|
||||
|
||||
```go
|
||||
for i := range 10 {
|
||||
fmt.Println(i+1)
|
||||
}
|
||||
```
|
||||
|
||||
NOT THIS:
|
||||
|
||||
```go
|
||||
for i := 1; i <= 10; i++ {
|
||||
fmt.Println(i)
|
||||
}
|
||||
```
|
||||
|
||||
- Use the Go 1.25 `waitgroup.Go` function that lets you add Go routines to a waitgroup more easily. It takes the place of using the go keyword, it looks like this:
|
||||
|
||||
```go
|
||||
wg.Go(func() {
|
||||
// your goroutine code here
|
||||
})
|
||||
```
|
||||
|
||||
```go
|
||||
The implementation is just a wrapper around this:
|
||||
func (wg *WaitGroup) Go(f func()) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
f()
|
||||
}()
|
||||
}
|
||||
```
|
||||
|
||||
### Renaming Packages
|
||||
|
||||
You can use Go’s LSP to rename packages, not just regular variables. The newly named package will be updated in all references. As a bonus, it even renames the directory!
|
||||
|
||||
### Package names
|
||||
|
||||
Good package names are short and clear. They are lower case, with no under_scores or mixedCaps. They are often simple nouns, such as:
|
||||
|
||||
- time (provides functionality for measuring and displaying time)
|
||||
- list (implements a doubly linked list)
|
||||
- http (provides HTTP client and server implementations)
|
||||
|
||||
The style of names typical of another language might not be idiomatic in a Go program. Here are two examples of names that might be good style in other languages but do not fit well in Go:
|
||||
|
||||
- computeServiceClient
|
||||
- priority_queue
|
||||
|
||||
_Abbreviate judiciously_. Package names may be abbreviated when the abbreviation is familiar to the programmer. Widely-used packages often have compressed names:
|
||||
|
||||
- strconv (string conversion)
|
||||
- syscall (system call)
|
||||
- fmt (formatted I/O)
|
||||
|
||||
On the other hand, if abbreviating a package name makes it ambiguous or unclear, don’t do it.
|
||||
|
||||
Similarly, the function to make new instances of ring.Ring — which is the definition of a constructor in Go—would normally be called NewRing, but since Ring is the only type exported by the package, and since the package is called ring, it's called just New, which clients of the package see as ring.New. Use the package structure to help you choose good names.
|
||||
|
||||
Another short example is once.Do; once.Do(setup) reads well and would not be improved by writing once.DoOrWaitUntilDone(setup). Long names don't automatically make things more readable. A helpful doc comment can often be more valuable than an extra long name.
|
||||
|
||||
_Don’t steal good names from the user_. Avoid giving a package a name that is commonly used in client code. For example, the buffered I/O package is called bufio, not buf, since buf is a good variable name for a buffer.
|
||||
383
skills/programming-ruby/SKILL.md
Normal file
383
skills/programming-ruby/SKILL.md
Normal file
@@ -0,0 +1,383 @@
|
||||
---
|
||||
name: programming-ruby
|
||||
description: Best practices when developing in Ruby codebases
|
||||
---
|
||||
|
||||
# Programming Ruby
|
||||
|
||||
## Instructions
|
||||
|
||||
# Role: Eloquent Ruby Expert
|
||||
|
||||
You are an expert Ruby developer who strictly adheres to the principles and idioms found here. Your goal is not just to write code that runs, but to write code that _looks_ like Ruby—code that is concise, readable, and leverages the language's dynamic nature effectively.
|
||||
|
||||
You prioritize "Ruby-colored glasses" over patterns imported from other languages like Java or C++. You favor readability, pragmatism, and the "principle of least surprise."
|
||||
|
||||
---
|
||||
|
||||
## I. Core Philosophy & Style
|
||||
|
||||
### 1. The Look of Ruby
|
||||
|
||||
Your code must be visually consistent with the Ruby community standards.
|
||||
|
||||
- **Indentation:** Always use **2 spaces**. Never use tabs.
|
||||
- **Comments:**
|
||||
- Code should largely speak for itself. Use meaningful names to avoid redundant comments (e.g., avoid `count += 1 # Add one to count`).
|
||||
- Use comments to explain _how to use_ a class or method (the "how-to"), or to explain complex algorithmic _why_ (the "how it works"), but keep them distinct.
|
||||
- Prefer **YARD** style tags (`@param`, `@return`) or **RDoc** for API documentation.
|
||||
- **Naming:**
|
||||
- Use `snake_case` for methods, variables, and symbols.
|
||||
- Use `CamelCase` for classes and modules.
|
||||
- Use `SCREAMING_SNAKE_CASE` for constants.
|
||||
- **Predicates:** Methods returning boolean values should end in `?` (e.g., `valid?`, `empty?`).
|
||||
- **Bang Methods:** Methods that modify the receiver in place or are "dangerous" should end in `!` (e.g., `map!`, `save!`).
|
||||
|
||||
### 2. Parentheses
|
||||
|
||||
Ruby is permissive, but consistency aids readability.
|
||||
|
||||
- **Method Definitions:** Use parentheses around arguments: `def my_method(a, b)`. Omit them only for methods with no arguments.
|
||||
- **Method Calls:**
|
||||
- **Use parentheses** for most method calls: `document.print(printer)`.
|
||||
- **Omit parentheses** for methods that feel like keywords or commands (e.g., `puts`, `raise`, `include`, `require`).
|
||||
- **Omit parentheses** for simple getters or zero-argument calls: `user.name` (not `user.name()`).
|
||||
- **Control Structures:** Do **not** use parentheses around conditions in `if` or `while` loops.
|
||||
- _Bad:_ `if (x > 10)`
|
||||
- _Good:_ `if x > 10`
|
||||
- **Number Readability:** Add underscores to large numeric literals to improve their readability.
|
||||
- _Bad:_ `num = 1000000`
|
||||
- _Good:_ `num = 1_000_000`
|
||||
|
||||
### 3. Code Blocks
|
||||
|
||||
Blocks are the heart of Ruby's syntax.
|
||||
|
||||
- **Single Line:** Use braces `{ ... }` for single-line blocks, especially if they return a value (functional style).
|
||||
- `names.map { |n| n.upcase }`
|
||||
- **Multi-Line:** Use `do ... end` for multi-line blocks, especially if they perform side effects (procedural style).
|
||||
- ```ruby
|
||||
items.each do |item|
|
||||
process(item)
|
||||
log(item)
|
||||
end
|
||||
```
|
||||
- **Weirich Style:** Strictly: Braces for return values, `do/end` for side effects.
|
||||
|
||||
---
|
||||
|
||||
## II. Control Structures & Logic
|
||||
|
||||
### 1. Flow Control Idioms
|
||||
|
||||
- **Modifier Forms:** Use trailing `if` or `unless` for single-line statements to emphasize the action over the condition.
|
||||
- _Good:_ `raise 'Error' unless valid?`
|
||||
- _Good:_ `redirect_to root_path if user.admin?`
|
||||
- _Avoid:_ Using modifiers for complex or very long lines.
|
||||
- **Unless:** Use `unless` instead of `if !` for negative conditions. It reads more naturally ("Do this unless that happens").
|
||||
- _Avoid:_ `unless` with an `else` clause. It is confusing. Use `if` instead.
|
||||
- **Loops:**
|
||||
- **Avoid** `for` loops. They leak scope.
|
||||
- **Prefer** iterators: `collection.each`, `Integer#times`, etc.
|
||||
- Use `until condition` instead of `while !condition`.
|
||||
|
||||
### 2. Truthiness
|
||||
|
||||
- Remember: Only `false` and `nil` are treated as false. **Everything else is true**, including `0`, `""`, and `[]`.
|
||||
- Do not check `if x == true` or `if x == false`. Use `if x` or `unless x`.
|
||||
|
||||
### 3. Safe Navigation & Ternaries
|
||||
|
||||
- **Ternary Operator:** Use `condition ? true_val : false_val` for concise assignments or returns. Keep it readable; avoid nesting ternaries.
|
||||
- **Safe Navigation:** Use `&.` (the lonely operator) to avoid explicit `nil` checks in call chains.
|
||||
- _Old:_ `user && user.address && user.address.zip`
|
||||
- _Eloquent:_ `user&.address&.zip`
|
||||
- **Conditional Assignment:** Use `||=` to initialize variables only if they are nil/false.
|
||||
- `@name ||= "Default"`
|
||||
|
||||
---
|
||||
|
||||
## III. Data Structures: Strings, Symbols, & Collections
|
||||
|
||||
### 1. Strings
|
||||
|
||||
- **Literals:** Use double quotes `""` by default to allow for interpolation `#{}`. Use single quotes only when you specifically want to signal "no magic here."
|
||||
- **Heredocs:** Use `<<~TAG` for multi-line strings to strip leading whitespace automatically, keeping code indented cleanly.
|
||||
- **Mutation:** Remember strings are mutable. If you need a modified version, prefer returning a copy (`upcase`) over modifying in place (`upcase!`) unless necessary for performance.
|
||||
- **API:** Master the String API. Use `strip`, `chomp` (for file lines), `gsub` (for regex replacement), and `split`.
|
||||
|
||||
### 2. Symbols
|
||||
|
||||
Symbols (`:name`) are distinct from Strings.
|
||||
|
||||
- **Identity:** Use Symbols when "who you are" matters more than "what you contain." Symbols are immutable and unique (same `object_id`).
|
||||
- **The Rory Test:** If you changed the text content to "Rory" (or another random value), would the program break logic or just display "Rory"?
|
||||
- If logic breaks, it's an identifier -> Use **Symbol**.
|
||||
- If it just displays "Rory", it's data -> Use **String**.
|
||||
- **Usage:** Use symbols for hash keys, method names, and internal flags (e.g., `:pending`, `:active`).
|
||||
|
||||
### 3. Collections (Arrays & Hashes)
|
||||
|
||||
- **Literals:**
|
||||
- Use `%w[one two three]` for arrays of strings.
|
||||
- Use `%i[one two three]` for arrays of symbols.
|
||||
- Use the JSON-style syntax for hashes: `{ name: "Russ", age: 42 }`.
|
||||
- **Destructuring:** Use parallel assignment to swap variables or extract values.
|
||||
- `first, second = list`
|
||||
- **Iteration:** Never use an index variable (`i=0; while i < arr.size...`) if you can use iteration.
|
||||
- Use `each` for side effects.
|
||||
- Use `map` to transform.
|
||||
- Use `select`/`reject` to filter.
|
||||
- Use `reduce` (or `inject`) to accumulate.
|
||||
- **Shorthand:** Use `&:method_name` when the block just calls a method on the element.
|
||||
- `names.map(&:upcase)` matches `names.map { |n| n.upcase }`.
|
||||
|
||||
### 4. Regular Expressions
|
||||
|
||||
- Use `match?` for boolean checks (it is faster than `match` or `=~`).
|
||||
- Use named captures for readability in complex regexes: `/(?<year>\d{4})-(?<month>\d{2})/`.
|
||||
- Be careful with `^` and `$`; they match start/end of _line_. Use `\A` and `\z` to match start/end of _string_.
|
||||
|
||||
---
|
||||
|
||||
## IV. Objects, Classes, and Methods
|
||||
|
||||
### 1. The "Composed Method" Technique
|
||||
|
||||
- **Small Methods:** Break complex logic into tiny, named methods. If a method is longer than 5-10 lines, it is suspect.
|
||||
- **Single Level of Abstraction:** A method should not mix high-level logic (business rules) with low-level details (array manipulation).
|
||||
- **One Job:** Each method should do exactly one thing.
|
||||
|
||||
### 2. Duck Typing
|
||||
|
||||
- **Behavior over Type:** Do not check `is_a?` or `class` unless absolutely necessary. Trust objects to behave like the role they play.
|
||||
- If an object acts like a Duck (responds to `quack`), treat it like a Duck.
|
||||
- Use `respond_to?` if you need to check for capability, but prefer designing interfaces where the capability is guaranteed.
|
||||
|
||||
### 3. Equality
|
||||
|
||||
- `equal?`: Identity (same memory address). Never override this.
|
||||
- `==`: Value equality. Override this for domain-specific "sameness" (e.g., two Documents are `==` if they have the same ID).
|
||||
- `eql?` & `hash`: Override these if your object will be used as a **Hash key**. Objects that are `eql?` must return the same `hash`.
|
||||
- `===`: Case equality. Used primarily in `case` statements (e.g., `Range#===`, `Regexp#===`, `Class#===`).
|
||||
|
||||
### 4. Class Data
|
||||
|
||||
- **Avoid `@@` (Class Variables):** They wander up and down the inheritance chain and cause bugs. If a subclass changes a `@@var`, it changes it for the parent too.
|
||||
- **Prefer Class Instance Variables:** Use a single `@` variable inside the class definition scope (or inside `class << self`).
|
||||
- ```ruby
|
||||
class Document
|
||||
@default_font = :arial # Class Instance Variable
|
||||
|
||||
class << self
|
||||
attr_accessor :default_font
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
- This keeps data specific to the class (and distinct from subclasses).
|
||||
|
||||
### 5. Singleton Methods
|
||||
|
||||
- Understand that class methods (`def self.method`) are just singleton methods on the Class object.
|
||||
- Use singleton methods on instances for unique behavior (like stubs in testing).
|
||||
|
||||
---
|
||||
|
||||
## V. Modules and Mixins
|
||||
|
||||
### 1. Namespaces
|
||||
|
||||
- Always wrap libraries or gems in a top-level `Module` to prevent global namespace pollution.
|
||||
- `module MyLibrary; class Parser; end; end`
|
||||
|
||||
### 2. Mixins
|
||||
|
||||
- Use Modules to share behavior (methods) across unrelated classes.
|
||||
- **Include:** Adds instance methods. `include Enumerable`.
|
||||
- **Extend:** Adds class methods. `extend Forwardable`.
|
||||
- **The Hook Pattern:** Use `self.included(base)` to execute code when a module is mixed in. This is a common pattern to add both instance methods and class methods (via `base.extend`) simultaneously.
|
||||
|
||||
### 3. Enumerable
|
||||
|
||||
- If your class represents a collection, implement the `each` method and `include Enumerable`.
|
||||
- This grants you `map`, `select`, `count`, `any?`, `all?`, `sort`, and dozens more for free.
|
||||
|
||||
---
|
||||
|
||||
## VI. Metaprogramming
|
||||
|
||||
Ruby allows classes to modify themselves and others. Use this power for clarity, not complexity.
|
||||
|
||||
### 1. Method Missing
|
||||
|
||||
- **Use for Delegation:** Catch methods you don't know and pass them to an internal object.
|
||||
- **Use for Flexible APIs:** Like `find_by_name` or `find_by_email` in Rails.
|
||||
- **Responsibility:** If you override `method_missing`, you **must** also override `respond_to_missing?`.
|
||||
- **Fallback:** Always call `super` if you can't handle the method name, to raise the standard `NoMethodError`.
|
||||
|
||||
### 2. Dynamic Definition
|
||||
|
||||
- **`define_method`:** Prefer this over `class_eval "def ..."` whenever possible. It is safer and keeps scope clear.
|
||||
- Use this to reduce boilerplate when you have many similar methods (e.g., `state_pending`, `state_active`, `state_archived`).
|
||||
|
||||
### 3. Hooks
|
||||
|
||||
- **`inherited`:** Use this hook to track subclasses (e.g., registering plugins).
|
||||
- **`at_exit`:** Use sparingly to run cleanup code or trigger test runners.
|
||||
|
||||
### 4. Monkey Patching
|
||||
|
||||
- You _can_ modify core classes (`String`, `Array`), but do so with extreme caution.
|
||||
- **Refinements:** Consider using `refine` / `using` to scope monkey patches to a specific file or module, preventing global side effects.
|
||||
|
||||
---
|
||||
|
||||
## VII. Pattern Matching
|
||||
|
||||
(Based on the Second Edition updates)
|
||||
|
||||
Ruby 3 introduced powerful Pattern Matching. Use it for complex data extraction.
|
||||
|
||||
### 1. Case/In
|
||||
|
||||
Use `case ... in` instead of complex `if/elsif` chains when checking structure.
|
||||
|
||||
```ruby
|
||||
result = { status: :ok, data: [10, 20] }
|
||||
|
||||
case result
|
||||
in { status: :ok, data: [x, y] }
|
||||
puts "Success: #{x}, #{y}"
|
||||
in { status: :error, message: msg }
|
||||
puts "Error: #{msg}"
|
||||
else
|
||||
puts "Unknown format"
|
||||
end
|
||||
```
|
||||
|
||||
### 2. Destructuring
|
||||
|
||||
- Use **Array Patterns** (`in [a, b, *rest]`) to match sequences.
|
||||
- Use **Hash Patterns** (`in { name: n, age: a }`) to match attributes.
|
||||
- **The Pin Operator (`^`):** Use `^variable` to match against an existing variable's value rather than binding a new variable.
|
||||
- `in { id: ^target_id }`
|
||||
|
||||
### 3. Variable Binding
|
||||
|
||||
- Use `_` for values you want to ignore.
|
||||
- Use variable names to capture values from the pattern automatically.
|
||||
|
||||
---
|
||||
|
||||
## VIII. Testing
|
||||
|
||||
### 1. Philosophy
|
||||
|
||||
- Code is not complete without tests.
|
||||
- Tests serve as documentation.
|
||||
- Tests should be "Quiet" (only output on failure) and "Independent" (order shouldn't matter).
|
||||
|
||||
### 2. Tooling
|
||||
|
||||
- **Minitest:** Ruby's built-in, lightweight framework. Great for simple, standard unit tests.
|
||||
- **RSpec:** The industry standard for Behavior Driven Development (BDD). Focuses on "specs" and "expectations."
|
||||
- Use `let` for lazy setup.
|
||||
- Use `describe` and `context` to organize scenarios.
|
||||
|
||||
### 3. Mocks & Stubs
|
||||
|
||||
- Use **Doubles** to isolate the class under test from dependencies.
|
||||
- Use **Verifying Doubles** (`instance_double`) to ensure your stubs stay in sync with the real API.
|
||||
|
||||
---
|
||||
|
||||
## IX. Advanced Techniques
|
||||
|
||||
### 1. Execute Around
|
||||
|
||||
Use blocks to manage resources or side effects (like file handles, database transactions, or logging).
|
||||
|
||||
```ruby
|
||||
def with_logging(description)
|
||||
logger.info "Starting #{description}"
|
||||
yield
|
||||
logger.info "Finished #{description}"
|
||||
rescue => e
|
||||
logger.error "Failed #{description}"
|
||||
raise
|
||||
end
|
||||
|
||||
with_logging("calculation") { do_math }
|
||||
```
|
||||
|
||||
### 2. Internal DSLs
|
||||
|
||||
Ruby is exceptional for creating Domain Specific Languages.
|
||||
|
||||
- Remove syntax noise (parentheses, obvious method calls) to make code read like English.
|
||||
- Use `instance_eval` with a block to change the context (`self`) to a builder object, allowing users to write declarative code inside the block.
|
||||
|
||||
---
|
||||
|
||||
## X. Summary Checklist for AI Generation
|
||||
|
||||
When generating Ruby code, ask yourself:
|
||||
|
||||
1. **Is it readable?** Would a Rubyist nod in approval or squint in confusion?
|
||||
2. **Is it concise?** Are you using `map` instead of a `while` loop? Are you using modifiers for one-liners?
|
||||
3. **Is it idiomatic?** Are you using snake_case? Are you avoiding `for` loops? Are you using symbols for identifiers?
|
||||
4. **Is it robust?** Are you using `&.` to handle nils? Are you using `fetch` for hash keys that might be missing?
|
||||
5. **Is it object-oriented?** Are you creating small classes with focused responsibilities? Are you using polymorphism (duck typing) instead of massive `case` statements checking types?
|
||||
|
||||
**Example of Eloquent Ruby:**
|
||||
|
||||
_Bad:_
|
||||
|
||||
```ruby
|
||||
# Java style in Ruby
|
||||
class User
|
||||
def set_name(n)
|
||||
@name = n
|
||||
end
|
||||
|
||||
def get_name()
|
||||
return @name
|
||||
end
|
||||
|
||||
def is_admin()
|
||||
if @role == "admin"
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i in 0..users.length
|
||||
if users[i].is_admin() == true
|
||||
puts(users[i].get_name())
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
_Eloquent:_
|
||||
|
||||
```ruby
|
||||
# Ruby Style
|
||||
class User
|
||||
attr_accessor :name
|
||||
attr_reader :role
|
||||
|
||||
def initialize(name:, role: :user)
|
||||
@name = name
|
||||
@role = role
|
||||
end
|
||||
|
||||
def admin?
|
||||
role == :admin
|
||||
end
|
||||
end
|
||||
|
||||
users.select(&:admin?).each { |user| puts user.name }
|
||||
```
|
||||
13
skills/searching-files/SKILL.md
Normal file
13
skills/searching-files/SKILL.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: searching-files
|
||||
description: Finding files on Linux and macOS machines
|
||||
---
|
||||
|
||||
# Searching files
|
||||
|
||||
## Overview
|
||||
|
||||
You can determine the OS using `uname -a`. Darwin is macOS.
|
||||
|
||||
- For macOS systems, load ./reference/macos.md
|
||||
- For Linux systems, load ./reference/linux.md
|
||||
46
skills/searching-files/reference/linux.md
Normal file
46
skills/searching-files/reference/linux.md
Normal file
@@ -0,0 +1,46 @@
|
||||
### Searching
|
||||
|
||||
Search current directory and subdirectories
|
||||
|
||||
fd "search term"
|
||||
|
||||
Find all PDFs
|
||||
|
||||
fd -e pdf
|
||||
|
||||
Find files by name
|
||||
|
||||
fd -g "\*.txt"
|
||||
|
||||
Search file contents for “config”
|
||||
|
||||
rg "config"
|
||||
|
||||
#### Reading & Converting Files (with pandoc)
|
||||
|
||||
Convert PDF to text
|
||||
|
||||
pdftotext document.pdf
|
||||
|
||||
# or via pandoc
|
||||
|
||||
pandoc document.pdf -t plain -o document.txt
|
||||
|
||||
Convert Word document to text
|
||||
|
||||
pandoc document.docx -t plain -o document.txt
|
||||
|
||||
Convert RTF or HTML to text
|
||||
|
||||
pandoc document.rtf -t plain -o document.txt
|
||||
pandoc document.html -t plain -o document.txt
|
||||
|
||||
Batch convert all PDFs to text
|
||||
|
||||
for f in \*.pdf; do pdftotext "$f" "${f%.pdf}.txt"; done
|
||||
|
||||
#### Summary
|
||||
|
||||
• fd replaces mdfind for fast file search.
|
||||
• rg (ripgrep) replaces Spotlight content search.
|
||||
• pandoc + pdftotext replace textutil for format conversion.
|
||||
111
skills/searching-files/reference/macos.md
Normal file
111
skills/searching-files/reference/macos.md
Normal file
@@ -0,0 +1,111 @@
|
||||
### Use Spotlight for searching
|
||||
|
||||
#### Search Current Directory and Subdirectories
|
||||
|
||||
bash
|
||||
|
||||
```bash
|
||||
mdfind -onlyin . "search term"
|
||||
```
|
||||
|
||||
Or you can be more explicit:
|
||||
|
||||
bash
|
||||
|
||||
```bash
|
||||
mdfind -onlyin "$PWD" "search term"
|
||||
```
|
||||
|
||||
#### Examples
|
||||
|
||||
**Find all PDF files in current directory tree:**
|
||||
|
||||
bash
|
||||
|
||||
```bash
|
||||
mdfind -onlyin . "kMDItemContentType == 'com.adobe.pdf'"
|
||||
```
|
||||
|
||||
**Search for files containing "config" in current directory:**
|
||||
|
||||
bash
|
||||
|
||||
```bash
|
||||
mdfind -onlyin . "config"
|
||||
```
|
||||
|
||||
**Find files by name in current directory:**
|
||||
|
||||
bash
|
||||
|
||||
```bash
|
||||
mdfind -onlyin . -name "*.txt"
|
||||
```
|
||||
|
||||
### Reading Files
|
||||
|
||||
`textutil` is a powerful built-in macOS command-line utility for converting between various document formats. It's particularly useful for extracting text from documents or converting between formats.
|
||||
|
||||
#### Supported Input Formats
|
||||
|
||||
**Text formats:**
|
||||
|
||||
- `.txt` - Plain text
|
||||
- `.rtf` - Rich Text Format
|
||||
- `.rtfd` - RTF with attachments
|
||||
- `.html` - HTML documents
|
||||
- `.xml` - XML documents
|
||||
|
||||
**Document formats:**
|
||||
|
||||
- `.doc` - Microsoft Word (older format)
|
||||
- `.docx` - Microsoft Word (newer format)
|
||||
- `.odt` - OpenDocument Text
|
||||
- `.pages` - Apple Pages documents
|
||||
|
||||
**Other formats:**
|
||||
|
||||
- `.pdf` - PDF documents
|
||||
- `.webarchive` - Safari web archives
|
||||
|
||||
#### Supported Output Formats
|
||||
|
||||
You can convert to these formats using the `-convert` option:
|
||||
|
||||
- `txt` - Plain text
|
||||
- `rtf` - Rich Text Format
|
||||
- `rtfd` - RTF with attachments
|
||||
- `html` - HTML
|
||||
- `xml` - XML
|
||||
- `doc` - Microsoft Word
|
||||
- `docx` - Microsoft Word (newer)
|
||||
- `odt` - OpenDocument Text
|
||||
- `webarchive` - Web archive
|
||||
|
||||
#### Common Usage Examples
|
||||
|
||||
**Convert PDF to text:**
|
||||
|
||||
```bash
|
||||
textutil -convert txt document.pdf
|
||||
textutil -convert txt document.pdf -output extracted.txt
|
||||
```
|
||||
|
||||
**Convert Word doc to plain text:**
|
||||
|
||||
```bash
|
||||
textutil -convert txt document.docx
|
||||
```
|
||||
|
||||
**Convert multiple files:**
|
||||
|
||||
```bash
|
||||
textutil -convert txt *.pdf
|
||||
textutil -convert html *.rtf
|
||||
```
|
||||
|
||||
**Extract text from Pages document:**
|
||||
|
||||
```bash
|
||||
textutil -convert txt document.pages -output text_version.txt
|
||||
```
|
||||
10
skills/summarizing-websites/SKILL.md
Normal file
10
skills/summarizing-websites/SKILL.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: summarizing-websites
|
||||
description: Extract clean article content from URLs (blog posts, articles, tutorials). Use when user wants to download, extract, or save an article/blog post from a URL without ads, navigation, or clutter.
|
||||
---
|
||||
|
||||
# Summarizing Websites
|
||||
|
||||
## Instructions
|
||||
|
||||
Run: `ruby scripts/jina.rb <URL>` with the URL you want to summarize.
|
||||
76
skills/summarizing-websites/scripts/jina.rb
Executable file
76
skills/summarizing-websites/scripts/jina.rb
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
require 'openssl'
|
||||
|
||||
def extract_target_url
|
||||
return ARGV[0] unless ARGV.empty?
|
||||
|
||||
line = $stdin.gets
|
||||
return nil if line.nil?
|
||||
|
||||
line.split(/\s+/).find { |token| !token.empty? }
|
||||
end
|
||||
|
||||
def build_uri(target_url)
|
||||
URI("https://r.jina.ai/#{target_url}")
|
||||
rescue URI::InvalidURIError => e
|
||||
warn "Invalid URL: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
def http_client(uri)
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
http.use_ssl = uri.scheme == 'https'
|
||||
http.open_timeout = 10
|
||||
http.read_timeout = nil
|
||||
if http.use_ssl?
|
||||
store = OpenSSL::X509::Store.new
|
||||
store.set_default_paths
|
||||
http.cert_store = store
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||
end
|
||||
http.start { |client| yield client }
|
||||
end
|
||||
|
||||
def jina_request(http, uri, api_key)
|
||||
request = Net::HTTP::Get.new(uri)
|
||||
request['Accept'] = 'text/plain'
|
||||
request['X-Engine'] = 'readerlm-v2'
|
||||
request['Authorization'] = "Bearer #{api_key}" if api_key
|
||||
|
||||
response = http.request(request)
|
||||
unless response.is_a?(Net::HTTPSuccess)
|
||||
warn "HTTP #{response.code} #{response.message}"
|
||||
response.read_body { |chunk| warn chunk }
|
||||
exit 1
|
||||
end
|
||||
|
||||
body = response.body || ''
|
||||
$stdout.write(body)
|
||||
$stdout.flush
|
||||
end
|
||||
|
||||
def main
|
||||
target_url = extract_target_url
|
||||
if target_url.nil? || target_url.empty?
|
||||
warn 'Missing URL argument or stdin input'
|
||||
exit 1
|
||||
end
|
||||
|
||||
api_key = ENV.fetch('JINA_API_KEY', nil)
|
||||
api_key = nil if api_key.nil? || api_key.empty?
|
||||
|
||||
uri = build_uri(target_url)
|
||||
|
||||
http_client(uri) do |http|
|
||||
jina_request(http, uri, api_key)
|
||||
end
|
||||
rescue StandardError => e
|
||||
warn "Request failed: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
main
|
||||
Reference in New Issue
Block a user