Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Changelog

All notable changes to Nutshell will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.4] - 2025-03-11

### Added
- Directory-level configuration with `.nutshell.json` files
- Configuration hierarchy: directory configs override user configs which override system configs
- Automatic config reloading when changing directories with `cd`
- Project-specific aliases and settings through directory configs
- Support for different themes per project

### Fixed
- Memory leak in directory path traversal
- Config loading order to properly respect precedence rules
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ TEST_SRC = $(wildcard tests/*.c)
TEST_OBJ = $(TEST_SRC:.c=.o)
TEST_BINS = $(TEST_SRC:.c=.test)

.PHONY: all clean install install-user test test-pkg test-theme test-ai release uninstall uninstall-user
.PHONY: all clean install install-user test test-pkg test-theme test-ai test-config test-dirconfig release uninstall uninstall-user

all: nutshell

Expand Down Expand Up @@ -116,6 +116,16 @@ test-ai: tests/test_ai_integration.test tests/test_openai_commands.test tests/te
@./tests/test_ai_shell_integration.test
@echo "All AI tests completed!"

# Add a new target for config tests
test-config: tests/test_config.test
@echo "Running configuration system tests..."
@./tests/test_config.test

# Add a target for directory config tests
test-dirconfig: tests/test_directory_config.test
@echo "Running directory config tests..."
@./tests/test_directory_config.test

# Update the test build rule to exclude main.o
tests/%.test: tests/%.o $(filter-out src/core/main.o, $(OBJ))
$(CC) -o $@ $^ $(LDFLAGS)
Expand Down
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,40 @@ This will switch to the "minimal" theme.

3. Switch to your theme with `theme mytheme`

## Directory-level Configuration

Nutshell now supports project-specific configurations through directory-level config files:

### How it works

- Nutshell searches for a `.nutshell.json` configuration file in the current directory
- If not found, it looks in parent directories until reaching your home directory
- Directory configs take precedence over user configs which take precedence over system configs
- Configurations are automatically reloaded when you change directories using `cd`

### Creating a directory config

Create a `.nutshell.json` file in your project directory:

```json
{
"theme": "minimal",
"aliases": {
"build": "make all",
"test": "make test",
"deploy": "scripts/deploy.sh"
},
"packages": ["gitify"]
}
```

### Benefits

- Project-specific aliases and settings
- Different themes for different projects
- Shared configurations for team projects (add `.nutshell.json` to version control)
- Hierarchical configuration (team settings in parent dir, personal tweaks in subdirs)

## Debugging

For development or troubleshooting, run the debug script:
Expand Down
11 changes: 11 additions & 0 deletions scripts/debug_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# Set debug environment variables
export NUT_DEBUG=1
export NUT_DEBUG_CONFIG=1

# Run the configuration test with debugging
make test-config

# Or run the shell with debugging
# make && ./nutshell
8 changes: 7 additions & 1 deletion src/core/executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <nutshell/core.h>
#include <nutshell/utils.h>
#include <nutshell/config.h> // Add this include for reload_directory_config
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
Expand Down Expand Up @@ -71,7 +72,12 @@ void execute_command(ParsedCommand *cmd) {

// Handle builtin commands without forking
if (strcmp(cmd->args[0], "cd") == 0) {
if (cmd->args[1]) chdir(cmd->args[1]);
if (cmd->args[1]) {
if (chdir(cmd->args[1]) == 0) {
// Successfully changed directory, reload directory-specific config
reload_directory_config();
}
}
return;
}

Expand Down
33 changes: 33 additions & 0 deletions src/core/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <nutshell/utils.h>
#include <nutshell/theme.h>
#include <nutshell/ai.h> // Add this include to access AI functions
#include <nutshell/config.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>
Expand Down Expand Up @@ -59,9 +60,38 @@ void shell_loop() {
char *input;
struct sigaction sa;

// Initialize the configuration system first
if (getenv("NUT_DEBUG")) {
DEBUG_LOG("Initializing configuration system");
}
init_config_system();

// Initialize the theme system
if (getenv("NUT_DEBUG")) {
DEBUG_LOG("Initializing theme system");
}
init_theme_system();

// Load saved theme from config if available
const char *saved_theme = get_config_theme();
if (saved_theme && current_theme && strcmp(current_theme->name, saved_theme) != 0) {
if (getenv("NUT_DEBUG")) {
DEBUG_LOG("Loading saved theme from config: %s", saved_theme);
}
Theme *theme = load_theme(saved_theme);
if (theme) {
if (current_theme) {
free_theme(current_theme);
}
current_theme = theme;
if (getenv("NUT_DEBUG")) {
DEBUG_LOG("Successfully loaded saved theme: %s", theme->name);
}
} else if (getenv("NUT_DEBUG")) {
DEBUG_LOG("Failed to load saved theme: %s", saved_theme);
}
}

// Initialize the AI shell integration
init_ai_shell();

Expand Down Expand Up @@ -245,6 +275,9 @@ void shell_loop() {

// Clean up theme system
cleanup_theme_system();

// Clean up configuration system
cleanup_config_system();
}

char *get_prompt() {
Expand Down
Loading
Loading