feat: add content adapter pattern for dynamic and remote files#17
Open
davydog187 wants to merge 2 commits intomainfrom
Open
feat: add content adapter pattern for dynamic and remote files#17davydog187 wants to merge 2 commits intomainfrom
davydog187 wants to merge 2 commits intomainfrom
Conversation
Adds support for different file content backends via an adapter protocol,
enabling function-backed, S3-backed, and other lazy content types.
## Changes
- Add ContentAdapter protocol for polymorphic content resolution
- Add FunctionContent adapter (anonymous fns, captured fns, MFA tuples)
- Add S3Content adapter scaffold (requires user-provided client)
- Modify InMemoryFs to resolve content through protocol
- Add materialize/2 and materialize_all/1 for caching lazy content
- Add JustBash.materialize_files/1 convenience function
- Update JustBash.new to accept content adapters and bare functions
- Add catch-all error clause to cat command for robust error handling
## Features
Files can now be:
- Static binaries: "/file.txt" => "content"
- Function-backed: "/file.txt" => fn -> "dynamic" end
- MFA tuples: FunctionContent.new({Module, :fun, [args]})
- S3-backed: S3Content.new(bucket: "b", key: "k", client: Client)
Function-backed files are resolved on each read. Use materialize_files/1
to cache results for repeated access.
## Testing
- 113 new tests covering protocol implementations and integration
- All existing tests pass (2510 total)
- Zero compilation warnings
- Example script demonstrates usage patterns
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update ContentAdapter protocol to receive and return bash state, allowing
function-backed files to read environment variables, access current directory,
and modify interpreter state during content resolution.
Breaking Changes:
- ContentAdapter.resolve/1 → resolve/2 (now receives bash parameter)
- Returns {:ok, binary, bash} instead of {:ok, binary}
- All 27 commands updated to thread bash state through file operations
- InMemoryFs.read_file, append_file, materialize functions updated
Improvements:
- FunctionContent supports 1-arity functions receiving bash state
- Functions can return {content, updated_bash} to modify state
- Sort command now uses locale-aware collation matching bash behavior
- All 2510 tests passing with full bash state integration
This enables dynamic file content that can:
- Access environment variables (e.g., fn bash -> bash.env["USER"] end)
- Read current working directory
- Modify bash state during file reads
- Track file access or implement custom behaviors
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
davydog187
commented
Feb 16, 2026
| """ | ||
|
|
||
| @type fun_spec :: | ||
| (-> String.t()) |
Collaborator
Author
There was a problem hiding this comment.
what does this think this is, Haskell?
There was a problem hiding this comment.
this is typespec for anon func with zero arity https://hexdocs.pm/elixir/typespecs.html#literals
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Adds support for different file content backends via an adapter protocol, enabling function-backed, S3-backed, and other lazy content types.
Motivation
The virtual filesystem previously only supported static binary content. This PR enables:
Implementation
Architecture
Uses an Elixir Protocol (
ContentAdapter) that dispatches on content data type:BitString- Identity implementation (existing binary content)FunctionContent- Calls function on each read (supports anonymous, captured, MFA)S3Content- Delegates to user-provided client (scaffold)Key Design Decisions
read_file/2changed one line to useContentAdapter.resolve(content). All 24+ commands work unchanged.materialize_files/1for caching, not hidden inread_file/2Changes
New Files:
lib/just_bash/fs/content_adapter.ex- Protocol definition + BitString impllib/just_bash/fs/content/function_content.ex- Function-backed contentlib/just_bash/fs/content/s3_content.ex- S3-backed content (scaffold)test/fs/content_adapter_test.exs- Protocol tests (17 tests)test/commands/content_adapter_integration_test.exs- Integration tests (35 tests)examples/content_adapters.exs- Usage examplesModified Files:
lib/just_bash/fs/in_memory_fs.ex- Use ContentAdapter protocol, add materialize functionslib/just_bash.ex- Support adapters in new/1, add materialize_files/1lib/just_bash/fs/fs.ex- Add materialize delegateslib/just_bash/commands/cat.ex- Add catch-all error clauseREADME.md- Document content adapterstest/in_memory_fs_test.exs- Add 61 tests for adapter functionalityUsage
Testing
--warnings-as-errorsBreaking Changes
None. The changes are fully backward compatible:
files: %{"/path" => "content"}works unchangedFuture Enhancements
Possible extensions:
🤖 Generated with Claude Code