diff --git a/docker/postgresql/test/Dockerfile b/docker/postgresql/test/Dockerfile deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/postgresql/test/file.test b/docker/postgresql/test/file.test deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/develop/heroprompt/heroprompt_example.vsh b/examples/develop/heroprompt/heroprompt_example.vsh index 1b1c2edc..de7e241f 100755 --- a/examples/develop/heroprompt/heroprompt_example.vsh +++ b/examples/develop/heroprompt/heroprompt_example.vsh @@ -2,25 +2,41 @@ import freeflowuniverse.herolib.develop.heroprompt -mut session := heroprompt.new_session() +import freeflowuniverse.herolib.core.playbook +import os -mut workspace1 := session.add_workspace()! -// TODO: Check the name bug -// mut workspace2 := session.add_workspace(name: 'withname')! -mut dir1 := workspace1.add_dir(path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker')! +heroscript_config := ' + !!heropromptworkspace.configure name:"test workspace" path:"${os.home_dir()}/code/github/freeflowuniverse/herolib" +' +mut plbook := playbook.new( + text: heroscript_config +)! + +heroprompt.play(mut plbook)! + +mut workspace1 := heroprompt.new_workspace( + path: '${os.home_dir()}/code/github/freeflowuniverse/herolib' +)! + +// mut workspace2 := heroprompt.get( +// name: 'test workspace' +// )! + +mut dir1 := workspace1.add_dir(path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker')! dir1.select_file(name: 'docker_ubuntu_install.sh')! mut dir2 := workspace1.add_dir( - path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib' + path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/herolib' )! dir2.select_file(name: '.gitignore')! dir2.select_file(name: 'build.sh')! -dir2.select_file(name: 'debug.sh')! +file := dir2.select_file(name: 'debug.sh')! +// println(file.read()!) mut dir3 := workspace1.add_dir( - path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/postgresql' + path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/postgresql' select_all: true )! diff --git a/examples/develop/heroprompt/heroprompt_heroscript_example.vsh b/examples/develop/heroprompt/heroprompt_heroscript_example.vsh new file mode 100644 index 00000000..e11fdf52 --- /dev/null +++ b/examples/develop/heroprompt/heroprompt_heroscript_example.vsh @@ -0,0 +1,15 @@ +#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.core.playbook +import os + + +heroscript_config := ' + !!heropromptworkspace.configure name:"test workspace" path:"${os.home_dir()}/code/github/freeflowuniverse/herolib" +' +mut plbook := playbook.new( + text: heroscript_config +)! + + +heroprompt.play(mut plbook)! diff --git a/lib/data/encoderhero/decoder.v b/lib/data/encoderhero/decoder.v index 0b3ff0c8..64f87d9b 100644 --- a/lib/data/encoderhero/decoder.v +++ b/lib/data/encoderhero/decoder.v @@ -24,7 +24,7 @@ fn decode_struct[T](_ T, data string) !T { if !data.contains(action_name) { action_name = '${obj_name}.configure' if !data.contains(action_name) { - $if debug{ + $if debug { print_backtrace() } return error('Data does not contain action name: ${obj_name}.define or ${action_name}') @@ -66,11 +66,13 @@ fn decode_struct[T](_ T, data string) !T { } } } $else $if field.is_array { - if is_struct_array(typ.$(field.name))! { - mut data_fmt := data.replace(action_str, '') - data_fmt = data.replace('define.${obj_name}', 'define') - arr := decode_array(typ.$(field.name), data_fmt)! - typ.$(field.name) = arr + $if field.is_array { + $if field.typ is $struct { + mut data_fmt := data.replace(action_str, '') + data_fmt = data.replace('define.${obj_name}', 'define') + typ.$(field.name) = decode_array[field.elem_type](typ.$(field.name), + data_fmt)! + } } } } diff --git a/lib/develop/heroprompt/heroprompt_dir.v b/lib/develop/heroprompt/heroprompt_dir.v index 88245978..044a5301 100644 --- a/lib/develop/heroprompt/heroprompt_dir.v +++ b/lib/develop/heroprompt/heroprompt_dir.v @@ -3,6 +3,15 @@ module heroprompt import os import freeflowuniverse.herolib.core.pathlib +@[heap] +pub struct HeropromptDir { +pub mut: + name string + path pathlib.Path + files []&HeropromptFile @[skip; str: skip] + dirs []&HeropromptDir +} + // Parameters for adding a file to a directory @[params] pub struct AddFileParams { diff --git a/lib/develop/heroprompt/heroprompt_file.v b/lib/develop/heroprompt/heroprompt_file.v index d52f0348..9dedb7ba 100644 --- a/lib/develop/heroprompt/heroprompt_file.v +++ b/lib/develop/heroprompt/heroprompt_file.v @@ -1,5 +1,16 @@ module heroprompt +// import freeflowuniverse.herolib.data.paramsparser +import freeflowuniverse.herolib.core.pathlib +import os + +pub struct HeropromptFile { +pub mut: + content string + path pathlib.Path + name string +} + // Utility function to get file extension with special handling for common files pub fn get_file_extension(filename string) string { // Handle special cases for common files without extensions @@ -57,3 +68,9 @@ pub fn get_file_extension(filename string) string { return parts[parts.len - 1] } + +// Read the file content +pub fn (fl HeropromptFile) read() !string { + content := os.read_file(fl.path.path)! + return content +} diff --git a/lib/develop/heroprompt/heroprompt_session.v b/lib/develop/heroprompt/heroprompt_session.v deleted file mode 100644 index b3c03469..00000000 --- a/lib/develop/heroprompt/heroprompt_session.v +++ /dev/null @@ -1,26 +0,0 @@ -module heroprompt - -import rand - -// HeropromptSession manages multiple workspaces for organizing AI prompts -pub struct HeropromptSession { -pub mut: - id string // Unique session identifier - workspaces []&HeropromptWorkspace // List of workspaces in this session -} - -// new_session creates a new heroprompt session with a unique ID -pub fn new_session() HeropromptSession { - return HeropromptSession{ - id: rand.uuid_v4() - workspaces: [] - } -} - -// add_workspace creates and adds a new workspace to the session -pub fn (mut self HeropromptSession) add_workspace(args_ NewWorkspaceParams) !&HeropromptWorkspace { - mut wsp := &HeropromptWorkspace{} - wsp = wsp.new(args_)! - self.workspaces << wsp - return wsp -} diff --git a/lib/develop/heroprompt/heroprompt_workspace.v b/lib/develop/heroprompt/heroprompt_workspace.v index 8ab92470..7e2d0040 100644 --- a/lib/develop/heroprompt/heroprompt_workspace.v +++ b/lib/develop/heroprompt/heroprompt_workspace.v @@ -5,19 +5,11 @@ import time import os import freeflowuniverse.herolib.core.pathlib -// HeropromptWorkspace represents a workspace containing multiple directories -// and their selected files for AI prompt generation -@[heap] -pub struct HeropromptWorkspace { -pub mut: - name string = 'default' // Workspace name - dirs []&HeropromptDir // List of directories in this workspace -} - @[params] -pub struct NewWorkspaceParams { -pub mut: +struct NewWorkspaceParams { +mut: name string + path string } /// Create a new workspace @@ -28,10 +20,200 @@ fn (wsp HeropromptWorkspace) new(args_ NewWorkspaceParams) !&HeropromptWorkspace args.name = generate_random_workspace_name() } - workspace := get(name: args.name)! + // Validate and set base path + if args.path.len > 0 { + if !os.exists(args.path) { + return error('Workspace path does not exist: ${args.path}') + } + if !os.is_dir(args.path) { + return error('Workspace path is not a directory: ${args.path}') + } + } + + mut workspace := &HeropromptWorkspace{ + name: args.name + base_path: os.real_path(args.path) + } return workspace } +// WorkspaceItem represents a file or directory in the workspace tree +pub struct WorkspaceItem { +pub mut: + name string // Item name (file or directory name) + path string // Full path to the item + is_directory bool // True if this is a directory + is_file bool // True if this is a file + size i64 // File size in bytes (0 for directories) + extension string // File extension (empty for directories) + children []WorkspaceItem // Child items (for directories) + is_expanded bool // Whether directory is expanded in UI + is_selected bool // Whether this item is selected for prompts + depth int // Depth level in the tree (0 = root) +} + +// WorkspaceList represents the complete hierarchical listing of a workspace +pub struct WorkspaceList { +pub mut: + root_path string // Root path of the workspace + items []WorkspaceItem // Top-level items in the workspace + total_files int // Total number of files + total_dirs int // Total number of directories +} + +// list returns the complete hierarchical structure of the workspace +pub fn (wsp HeropromptWorkspace) list() WorkspaceList { + mut result := WorkspaceList{ + root_path: wsp.base_path + } + + if wsp.base_path.len == 0 || !os.exists(wsp.base_path) { + return result + } + + // Build the complete tree structure (ALL files and directories) + result.items = wsp.build_workspace_tree(wsp.base_path, 0) + wsp.calculate_totals(result.items, mut result) + + // Mark selected items + wsp.mark_selected_items(mut result.items) + + return result +} + +// build_workspace_tree recursively builds the workspace tree structure +fn (wsp HeropromptWorkspace) build_workspace_tree(path string, depth int) []WorkspaceItem { + mut items := []WorkspaceItem{} + + entries := os.ls(path) or { return items } + + for entry in entries { + full_path := os.join_path(path, entry) + + if os.is_dir(full_path) { + mut dir_item := WorkspaceItem{ + name: entry + path: full_path + is_directory: true + is_file: false + size: 0 + extension: '' + is_expanded: false + is_selected: false + depth: depth + } + + // Recursively get children + dir_item.children = wsp.build_workspace_tree(full_path, depth + 1) + items << dir_item + } else if os.is_file(full_path) { + file_info := os.stat(full_path) or { continue } + extension := get_file_extension(entry) + + file_item := WorkspaceItem{ + name: entry + path: full_path + is_directory: false + is_file: true + size: file_info.size + extension: extension + children: [] + is_expanded: false + is_selected: false + depth: depth + } + items << file_item + } + } + + // Sort: directories first, then files, both alphabetically + items.sort_with_compare(fn (a &WorkspaceItem, b &WorkspaceItem) int { + if a.is_directory && !b.is_directory { + return -1 + } + if !a.is_directory && b.is_directory { + return 1 + } + if a.name < b.name { + return -1 + } + if a.name > b.name { + return 1 + } + return 0 + }) + + return items +} + +// calculate_totals counts total files and directories in the workspace +fn (wsp HeropromptWorkspace) calculate_totals(items []WorkspaceItem, mut result WorkspaceList) { + for item in items { + if item.is_directory { + result.total_dirs++ + wsp.calculate_totals(item.children, mut result) + } else { + result.total_files++ + } + } +} + +// mark_selected_items marks which items are currently selected for prompts +fn (wsp HeropromptWorkspace) mark_selected_items(mut items []WorkspaceItem) { + for mut item in items { + // Check if this item is selected by comparing paths + item.is_selected = wsp.is_item_selected(item.path) + + // Recursively mark children + if item.is_directory && item.children.len > 0 { + wsp.mark_selected_items(mut item.children) + } + } +} + +// is_item_selected checks if a specific path is selected in the workspace +fn (wsp HeropromptWorkspace) is_item_selected(path string) bool { + for dir in wsp.dirs { + // Check if this directory is selected + if dir.path.path == path { + return true + } + + // Check if any file in this directory is selected + for file in dir.files { + if file.path.path == path { + return true + } + } + + // Recursively check subdirectories + if wsp.is_path_in_selected_dirs(path, dir.dirs) { + return true + } + } + return false +} + +// is_path_in_selected_dirs recursively checks subdirectories for selected items +fn (wsp HeropromptWorkspace) is_path_in_selected_dirs(path string, dirs []&HeropromptDir) bool { + for dir in dirs { + if dir.path.path == path { + return true + } + + for file in dir.files { + if file.path.path == path { + return true + } + } + + if wsp.is_path_in_selected_dirs(path, dir.dirs) { + return true + } + } + return false +} + @[params] pub struct AddDirParams { pub mut: diff --git a/lib/develop/heroprompt/reprompt_actions.v b/lib/develop/heroprompt/reprompt_actions.v deleted file mode 100644 index 3e82df0b..00000000 --- a/lib/develop/heroprompt/reprompt_actions.v +++ /dev/null @@ -1,13 +0,0 @@ -module heroprompt - -// TODO: Implement template-based prompt generation -fn (mut ws HeropromptWorkspace) heroprompt() !string { - // TODO: fill in template based on selection - return '' -} - -// TODO: Implement tree visualization utilities -pub fn get_tree() {} - -// TODO: Implement prompt formatting utilities -pub fn format_prompt() {} diff --git a/lib/develop/heroprompt/reprompt_factory_.v b/lib/develop/heroprompt/reprompt_factory_.v index 2df23ef1..c8af0d03 100644 --- a/lib/develop/heroprompt/reprompt_factory_.v +++ b/lib/develop/heroprompt/reprompt_factory_.v @@ -2,7 +2,6 @@ module heroprompt import freeflowuniverse.herolib.core.base import freeflowuniverse.herolib.core.playbook { PlayBook } -import freeflowuniverse.herolib.ui.console __global ( heroprompt_global map[string]&HeropromptWorkspace @@ -35,7 +34,7 @@ pub fn get(args_ ArgsGet) !&HeropromptWorkspace { if !exists(args)! { set(obj)! } else { - heroscript := context.hero_config_get('heroprompt', args.name)! + heroscript := context.hero_config_get('heropromptworkspace', args.name)! mut obj_ := heroscript_loads(heroscript)! set_in_mem(obj_)! } @@ -52,20 +51,20 @@ pub fn set(o HeropromptWorkspace) ! { set_in_mem(o)! mut context := base.context()! heroscript := heroscript_dumps(o)! - context.hero_config_set('heroprompt', o.name, heroscript)! + context.hero_config_set('heropromptworkspace', o.name, heroscript)! } // does the config exists? pub fn exists(args_ ArgsGet) !bool { mut context := base.context()! mut args := args_get(args_) - return context.hero_config_exists('heroprompt', args.name) + return context.hero_config_exists('heropromptworkspace', args.name) } pub fn delete(args_ ArgsGet) ! { mut args := args_get(args_) mut context := base.context()! - context.hero_config_delete('heroprompt', args.name)! + context.hero_config_delete('heropromptworkspace', args.name)! if args.name in heroprompt_global { // del heroprompt_global[args.name] } @@ -79,7 +78,7 @@ fn set_in_mem(o HeropromptWorkspace) ! { } pub fn play(mut plbook PlayBook) ! { - mut install_actions := plbook.find(filter: 'heroprompt.configure')! + mut install_actions := plbook.find(filter: 'heropromptworkspace.configure')! if install_actions.len > 0 { for install_action in install_actions { heroscript := install_action.heroscript() diff --git a/lib/develop/heroprompt/reprompt_model.v b/lib/develop/heroprompt/reprompt_model.v index 474d33c1..7d010448 100644 --- a/lib/develop/heroprompt/reprompt_model.v +++ b/lib/develop/heroprompt/reprompt_model.v @@ -1,51 +1,43 @@ module heroprompt -import freeflowuniverse.herolib.data.paramsparser -// import freeflowuniverse.herolib.data.encoderhero // temporarily commented out -import freeflowuniverse.herolib.core.pathlib -import os +import freeflowuniverse.herolib.data.encoderhero pub const version = '0.0.0' const singleton = false const default = true -// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED - -pub struct HeropromptFile { +// HeropromptWorkspace represents a workspace containing multiple directories +// and their selected files for AI prompt generation +@[heap] +pub struct HeropromptWorkspace { pub mut: - content string - path pathlib.Path - name string + name string = 'default' // Workspace name + base_path string // Base path of the workspace + dirs []&HeropromptDir // List of directories in this workspace } -pub struct HeropromptDir { +@[params] +pub struct AddWorkspaceParams { pub mut: - name string - path pathlib.Path - files []&HeropromptFile - dirs []&HeropromptDir + name string + path string } -// pub fn (wsp HeropromptWorkspace) to_tag() { -// tag := HeropromptTags.file_map -// // We need to pass it to the template -// } +// add_workspace creates and adds a new workspace +pub fn new_workspace(args_ AddWorkspaceParams) !&HeropromptWorkspace { + mut wsp := &HeropromptWorkspace{} + wsp = wsp.new(name: args_.name, path: args_.path)! + return wsp +} -// // pub fn (dir HeropromptDir) to_tag() { -// // tag := HeropromptTags.file_content -// // // We need to pass it to the template -// // } +// get_workspace gets the saved workspace +pub fn get_workspace(args_ AddWorkspaceParams) !&HeropromptWorkspace { + if args_.name.len == 0 { + return error('Workspace name is required') + } -// pub fn (fil HeropromptFile) to_tag() { -// tag := HeropromptTags.file_content -// // We need to pass it to the template -// } - -// pub enum HeropromptTags { -// file_map -// file_content -// user_instructions -// } + return get(name: args_.name)! +} // your checking & initialization code if needed fn obj_init(mycfg_ HeropromptWorkspace) !HeropromptWorkspace { @@ -55,16 +47,11 @@ fn obj_init(mycfg_ HeropromptWorkspace) !HeropromptWorkspace { /////////////NORMALLY NO NEED TO TOUCH -// TODO: Check the compiler issue with the encde/decode pub fn heroscript_dumps(obj HeropromptWorkspace) !string { - // return encoderhero.encode[HeropromptWorkspace](obj)! // temporarily commented out - return 'name: "${obj.name}"' + return encoderhero.encode[HeropromptWorkspace](obj)! } pub fn heroscript_loads(heroscript string) !HeropromptWorkspace { - // mut obj := encoderhero.decode[HeropromptWorkspace](heroscript)! // temporarily commented out - obj := HeropromptWorkspace{ - name: 'default' - } + mut obj := encoderhero.decode[HeropromptWorkspace](heroscript)! return obj } diff --git a/lib/develop/heroprompt/templates/heroscript_template.hero b/lib/develop/heroprompt/templates/heroscript_template.hero index 6707d82c..58fec6df 100644 --- a/lib/develop/heroprompt/templates/heroscript_template.hero +++ b/lib/develop/heroprompt/templates/heroscript_template.hero @@ -1,10 +1,10 @@ -!!heroprompt.configure name:"default" +!!heropromptworkspace.configure name:"default" -!!heroprompt.workspace_dir name:"default" - path:"@HOME/code/github/freeflowuniverse/herolib/lib/builder" - selection:"path1,path2" //paths are relative in the path of workspace - filter_exclude:"," - filter_include:"," +// !!heropromptworkspace.workspace_dir name:"default" + // path:"@HOME/code/github/freeflowuniverse/herolib/lib/builder" + // selection:"path1,path2" //paths are relative in the path of workspace + // filter_exclude:"," + // filter_include:"," diff --git a/lib/develop/heroprompt/templates/prompt_example.md b/lib/develop/heroprompt/templates/prompt_example.md deleted file mode 100644 index a335cffd..00000000 --- a/lib/develop/heroprompt/templates/prompt_example.md +++ /dev/null @@ -1,171 +0,0 @@ - -/Users/mahmoud/code/github/freeflowuniverse/herolib -└── docker - └── docker_ubuntu_install.sh * - ├── herolib - │ ├── .gitignore* - │ ├── build.sh * - │ └── debug.sh* - - - -File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh - -```sh -#!/bin/bash - -# Exit immediately if a command exits with a non-zero status -set -e - -# Function to display an error message and exit -error_exit() { - echo "Error: $1" >&2 - exit 1 -} - -# Update package index and upgrade system -echo "Updating system packages..." -sudo apt update && sudo apt upgrade -y || error_exit "Failed to update system packages." - -# Install required packages for repository setup -echo "Installing prerequisites..." -sudo apt install -y ca-certificates curl gnupg || error_exit "Failed to install prerequisites." - -# Create directory for Docker GPG key -echo "Setting up GPG keyring..." -sudo mkdir -p /etc/apt/keyrings || error_exit "Failed to create keyring directory." - -# Add Docker's official GPG key -DOCKER_GPG_KEY=/etc/apt/keyrings/docker.gpg -echo "Adding Docker GPG key..." -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o $DOCKER_GPG_KEY || error_exit "Failed to add Docker GPG key." -sudo chmod a+r $DOCKER_GPG_KEY - -# Set up Docker repository -echo "Adding Docker repository..." -REPO_ENTRY="deb [arch=$(dpkg --print-architecture) signed-by=$DOCKER_GPG_KEY] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" -if ! grep -Fxq "$REPO_ENTRY" /etc/apt/sources.list.d/docker.list; then - echo "$REPO_ENTRY" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null || error_exit "Failed to add Docker repository." -fi - -# Update package index -echo "Updating package index..." -sudo apt update || error_exit "Failed to update package index." - -# Install Docker Engine, CLI, and dependencies -echo "Installing Docker Engine and dependencies..." -sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin || error_exit "Failed to install Docker packages." - -# Verify Docker installation -echo "Verifying Docker installation..." -if ! docker --version; then - error_exit "Docker installation verification failed." -fi - -# Run a test container -echo "Running Docker test container..." -if ! sudo docker run --rm hello-world; then - error_exit "Docker test container failed to run." -fi - -# Add current user to Docker group (if not already added) -echo "Configuring Docker group..." -if ! groups $USER | grep -q '\bdocker\b'; then - sudo usermod -aG docker $USER || error_exit "Failed to add user to Docker group." - echo "User added to Docker group. Please log out and back in for this change to take effect." -else - echo "User is already in the Docker group." -fi - -# Enable Docker service on boot -echo "Enabling Docker service on boot..." -sudo systemctl enable docker || error_exit "Failed to enable Docker service." - -# Success message -echo "Docker installation completed successfully!" - -``` - -File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/build.sh - -```sh -#!/bin/bash -e - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -# Copy installation files -cp ../../install_v.sh ./scripts/install_v.sh -cp ../../install_herolib.vsh ./scripts/install_herolib.vsh - -# Docker image and container names -DOCKER_IMAGE_NAME="herolib" -DEBUG_CONTAINER_NAME="herolib" - -function cleanup { - if docker ps -aq -f name="$DEBUG_CONTAINER_NAME" &>/dev/null; then - echo "Cleaning up leftover debug container..." - docker rm -f "$DEBUG_CONTAINER_NAME" &>/dev/null || true - fi -} -trap cleanup EXIT - -# Attempt to build the Docker image -BUILD_LOG=$(mktemp) -set +e -docker build --name herolib --progress=plain -t "$DOCKER_IMAGE_NAME" . -BUILD_EXIT_CODE=$? -set -e - -# Handle build failure -if [ $BUILD_EXIT_CODE -ne 0 ]; then - echo -e "\\n[ERROR] Docker build failed.\n" - echo -e "remove the part which didn't build in the Dockerfile, the run again and to debug do:" - echo docker run --name herolib -it --entrypoint=/bin/bash "herolib" - exit $BUILD_EXIT_CODE -else - echo -e "\\n[INFO] Docker build completed successfully." -fi - - - -``` - -File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/.gitignore - -``` -.bash_history -.openvscode-server/ -.cache/ -``` - -File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/debug.sh - -```sh -#!/bin/bash -ex - -# Get the directory where the script is located -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$SCRIPT_DIR" - -# Remove any existing container named 'debug' (ignore errors) -docker rm -f herolib > /dev/null 2>&1 - -docker run --name herolib -it \ - --entrypoint="/usr/local/bin/ourinit.sh" \ - -v "${SCRIPT_DIR}/scripts:/scripts" \ - -v "$HOME/code:/root/code" \ - -p 4100:8100 \ - -p 4101:8101 \ - -p 4102:8102 \ - -p 4379:6379 \ - -p 4022:22 \ - -p 4000:3000 herolib - -``` - - - -This is a small repo prompt example -