diff --git a/install/bash/examples.sh b/install/bash/examples.sh index 54bbc342..5652ea98 100644 --- a/install/bash/examples.sh +++ b/install/bash/examples.sh @@ -5,6 +5,7 @@ set -euo pipefail # Brand Colors (use exported colors if available, otherwise define them) YELLOW="${YELLOW:-\033[38;2;224;255;110m}" GREEN="${GREEN:-\033[38;2;121;252;150m}" +WHITE="${WHITE:-\033[38;2;255;255;255m}" RED="${RED:-\033[38;2;239;68;68m}" GRAY="${GRAY:-\033[38;2;128;128;128m}" BOLD="${BOLD:-\033[1m}" @@ -16,9 +17,9 @@ EXAMPLES_DOWNLOAD_URL="https://github.com/Codeplain-ai/plainlang-examples/archiv # Show current directory and ask for extraction path CURRENT_DIR=$(pwd) -echo -e " current folder: ${YELLOW}${CURRENT_DIR}${NC}" +echo -e " Current folder: ${WHITE}${CURRENT_DIR}${NC}" echo "" -echo -e " extract examples here, or enter a different path:" +echo -e " Extract examples here, or enter a different path:" echo "" read -r -p " [Enter for current, or type path]: " EXTRACT_PATH < /dev/tty echo "" @@ -35,24 +36,24 @@ SKIP_DOWNLOAD=false # Check if directory exists, create if not if [ ! -d "$EXTRACT_PATH" ]; then - echo -e " ${GRAY}creating directory...${NC}" + echo -e " ${GRAY}Creating directory...${NC}" mkdir -p "$EXTRACT_PATH" 2>/dev/null if [ $? -ne 0 ]; then - echo -e " ${RED}✗${NC} failed to create directory: ${EXTRACT_PATH}" - echo -e " ${GRAY}skipping example download.${NC}" + echo -e " ${RED}✗ Failed to create directory: ${EXTRACT_PATH}${NC}" + echo -e " ${GRAY}Skipping example download.${NC}" SKIP_DOWNLOAD=true fi fi if [ "$SKIP_DOWNLOAD" = false ]; then - echo -e " ${GRAY}downloading examples...${NC}" + echo -e " ${GRAY}Downloading examples...${NC}" # Download the zip file TEMP_ZIP=$(mktemp) curl -L -s -o "$TEMP_ZIP" "$EXAMPLES_DOWNLOAD_URL" if [ $? -eq 0 ] && [ -s "$TEMP_ZIP" ]; then - echo -e " ${GRAY}extracting to ${EXTRACT_PATH}...${NC}" + echo -e " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}" # Extract the zip file unzip -q -o "$TEMP_ZIP" -d "$EXTRACT_PATH" 2>/dev/null @@ -71,22 +72,32 @@ if [ "$SKIP_DOWNLOAD" = false ]; then rm -f "${EXTRACTED_DIR}/.gitignore" fi + clear echo "" - echo -e " ${GREEN}✓${NC} examples downloaded successfully!" + echo -e " ${GREEN}✓ Examples downloaded successfully!${NC}" echo "" - echo -e " examples are in: ${YELLOW}${EXTRACTED_DIR}${NC}" + echo -e " ${GRAY}Examples are in: ${EXTRACTED_DIR}${NC}" + echo "" + echo -e " ${WHITE}${BOLD}Try the hello, world example:${NC}" + echo "" + echo -e " ${GRAY}Example folder:${NC} ${WHITE}cd ${EXTRACTED_DIR}/hello-world/python${NC}" + echo "" + echo -e " ${GRAY}Render the example:${NC} ${WHITE}codeplain hello-world-python.plain${NC}" + echo "" + echo -e " ${GRAY}See hello-world/python/README.md for details.${NC}" echo "" else - echo -e " ${RED}✗${NC} failed to extract examples." + echo -e " ${RED}✗ Failed to extract examples.${NC}" fi # Clean up temp file rm -f "$TEMP_ZIP" else - echo -e " ${RED}✗${NC} failed to download examples." + echo -e " ${RED}✗ Failed to download examples.${NC}" rm -f "$TEMP_ZIP" fi echo "" - read -r -p " press [Enter] to continue..." < /dev/tty + PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...") + read -r -p "$PROMPT" < /dev/tty fi diff --git a/install/bash/install.sh b/install/bash/install.sh index 6e903cd2..d66b753e 100755 --- a/install/bash/install.sh +++ b/install/bash/install.sh @@ -25,15 +25,15 @@ export YELLOW GREEN GREEN_LIGHT GREEN_DARK BLUE BLACK WHITE RED GRAY GRAY_LIGHT NONINTERACTIVE="${CODEPLAIN_INSTALL_NONINTERACTIVE:-0}" if [ "$NONINTERACTIVE" = "1" ]; then - echo "running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)" + echo "Running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)" else clear fi -echo -e "started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..." +echo -e "Started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..." # Install uv if not present install_uv() { - echo -e "installing uv package manager..." + echo -e "Installing uv package manager..." curl -LsSf https://astral.sh/uv/install.sh | sh # Add uv to PATH for this session export PATH="$HOME/.local/bin:$PATH" @@ -54,7 +54,7 @@ echo -e "" if uv tool list 2>/dev/null | grep -q "^codeplain"; then CURRENT_VERSION=$(uv tool list 2>/dev/null | grep "^codeplain" | sed 's/codeplain v//') echo -e "${GRAY}codeplain ${CURRENT_VERSION} is already installed.${NC}" - echo -e "upgrading to latest version..." + echo -e "Upgrading to latest version..." echo -e "" uv tool upgrade codeplain &> /dev/null NEW_VERSION=$(uv tool list 2>/dev/null | grep "^codeplain" | sed 's/codeplain v//') @@ -64,7 +64,7 @@ if uv tool list 2>/dev/null | grep -q "^codeplain"; then echo -e "${GREEN}✓${NC} codeplain upgraded from ${CURRENT_VERSION} to ${NEW_VERSION}!" fi else - echo -e "installing codeplain...${NC}" + echo -e "Installing codeplain...${NC}" echo -e "" uv tool install codeplain if [ "$NONINTERACTIVE" != "1" ]; then @@ -77,18 +77,18 @@ fi SKIP_API_KEY_SETUP=false if [ -n "${CODEPLAIN_API_KEY:-}" ]; then if [ "$NONINTERACTIVE" = "1" ]; then - echo -e "${GREEN}✓${NC} using existing CODEPLAIN_API_KEY (non-interactive mode)." + echo -e "${GREEN}✓${NC} Using existing CODEPLAIN_API_KEY (non-interactive mode)." SKIP_API_KEY_SETUP=true else - echo -e " you already have an API key configured." + echo -e " You already have an API key configured." echo "" - echo -e " would you like to log in and get a new one?" + echo -e "${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to log in and get a new one?${NC}" echo "" - read -r -p " [y/N]: " GET_NEW_KEY < /dev/tty + read -r -p " [y/N]: " GET_NEW_KEY < /dev/tty echo "" if [[ ! "$GET_NEW_KEY" =~ ^[Yy]$ ]]; then - echo -e "${GREEN}✓${NC} using existing API key." + echo -e "${GREEN}✓${NC} Using existing API key." SKIP_API_KEY_SETUP=true fi fi @@ -96,11 +96,11 @@ fi if [ "$SKIP_API_KEY_SETUP" = false ]; then if [ "$NONINTERACTIVE" = "1" ]; then - echo -e "${GRAY}no CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}" + echo -e "${GRAY}No CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}" else - echo -e "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key." + echo -e "Go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key." echo "" - read -r -p "paste your API key here: " API_KEY < /dev/tty + read -r -p "Paste your API key here: " API_KEY < /dev/tty echo "" fi fi @@ -108,7 +108,7 @@ fi if [ "$SKIP_API_KEY_SETUP" = true ]; then : # API key already set, nothing to do elif [ -z "${API_KEY:-}" ]; then - echo -e "${GRAY}no API key provided. you can set it later with:${NC}" + echo -e "${GRAY}No API key provided. You can set it later with:${NC}" echo -e " export CODEPLAIN_API_KEY=\"your_api_key\"" else # Export for current session @@ -150,10 +150,6 @@ fi if [ "$NONINTERACTIVE" != "1" ]; then clear fi -echo "" -echo -e "${NC}" -echo -e "${GRAY}────────────────────────────────────────────${NC}" -echo -e "" cat << 'EOF' _ _ _ ___ ___ __| | ___ _ __ | | __ _(_)_ __ @@ -163,19 +159,16 @@ cat << 'EOF' |_| EOF echo "" -echo -e "${GREEN}✓${NC} Sign in successful." -echo "" -echo -e " ${YELLOW}welcome to *codeplain!${NC}" +echo -e "${GREEN}✓ Sign in successful.${NC}" echo "" -echo -e " spec-driven, production-ready code generation" +echo -e " ${WHITE}Welcome to *codeplain!${NC}" echo "" -echo "" -echo -e "${GRAY}────────────────────────────────────────────${NC}" +echo -e " ${GRAY}Spec-driven, production-ready code generation${NC}" echo "" if [ "$NONINTERACTIVE" = "1" ]; then WALKTHROUGH_CHOICE="n" else - echo -e " would you like to get a quick intro to ***plain specification language?" + echo -e "${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to get a quick intro to ***plain specification language?${NC}" echo "" read -r -p " [Y/n]: " WALKTHROUGH_CHOICE < /dev/tty echo "" @@ -215,20 +208,95 @@ if [[ ! "$WALKTHROUGH_CHOICE" =~ ^[Nn]$ ]]; then run_script "walkthrough.sh" fi +# Install plain-forge step +if [ "$NONINTERACTIVE" = "1" ]; then + INSTALL_PLAIN_FORGE="n" +else + clear + echo "" + echo -e " ${YELLOW}${BOLD}plain-forge${NC}" + echo "" + echo -e " plain-forge plugs into your AI coding agent (Claude Code, Codex," + echo -e " ForgeCode, OpenCode, ...) and turns a conversation into a" + echo -e " complete ***plain spec, keeping it maintained as you grow it." + echo "" + echo -e " ${GRAY}Read more: https://github.com/Codeplain-ai/plain-forge${NC}" + echo "" + echo -e " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to install it now?${NC}" + echo "" + read -r -p " [Y/n]: " INSTALL_PLAIN_FORGE < /dev/tty + echo "" +fi + +PLAIN_FORGE_INSTALLED=false +if [[ ! "${INSTALL_PLAIN_FORGE:-}" =~ ^[Nn]$ ]]; then + if command -v npx &> /dev/null; then + npx plain-forge install < /dev/tty + PLAIN_FORGE_INSTALLED=true + echo "" + else + echo -e "${GRAY}npx not found. Install Node.js, then run:${NC}" + echo -e " npx plain-forge install" + echo "" + fi +fi + +# Install plyn editor extension step +EDITOR_CMDS=() +command -v cursor &> /dev/null && EDITOR_CMDS+=("cursor:Cursor") +command -v code &> /dev/null && EDITOR_CMDS+=("code:VS Code") + +if [ "$NONINTERACTIVE" = "1" ]; then + INSTALL_PLYN="n" +else + clear + echo "" + echo -e "${GRAY}────────────────────────────────────────────${NC}" + echo -e " ${YELLOW}${BOLD}plyn Editor Extension${NC}" + echo -e "${GRAY}────────────────────────────────────────────${NC}" + echo "" + echo -e " plyn adds ***plain syntax highlighting to VS Code and Cursor." + echo "" + if [ "${#EDITOR_CMDS[@]}" -gt 0 ]; then + EDITOR_NAMES=$(printf '%s, ' "${EDITOR_CMDS[@]#*:}") + echo -e " Detected ${EDITOR_NAMES%, }." + echo "" + echo -e " ${YELLOW}?${NC} ${WHITE}${BOLD}Install the extension now?${NC}" + echo "" + read -r -p " [Y/n]: " INSTALL_PLYN < /dev/tty + echo "" + else + echo -e " Install it manually from:" + echo -e " ${YELLOW}https://marketplace.visualstudio.com/items?itemName=Codeplain.plyn${NC}" + echo "" + INSTALL_PLYN="n" + fi +fi + +PLYN_INSTALLED=false +if [ "${#EDITOR_CMDS[@]}" -gt 0 ] && [[ ! "${INSTALL_PLYN:-}" =~ ^[Nn]$ ]]; then + for entry in "${EDITOR_CMDS[@]}"; do + editor_cmd="${entry%%:*}" + editor_name="${entry#*:}" + "$editor_cmd" --install-extension Codeplain.plyn + echo -e "${GREEN}✓${NC} plyn installed for ${editor_name}" + done + PLYN_INSTALLED=true + echo "" +fi + # Download examples step if [ "$NONINTERACTIVE" = "1" ]; then DOWNLOAD_EXAMPLES="n" else clear echo "" - echo -e "${GRAY}────────────────────────────────────────────${NC}" echo -e " ${YELLOW}${BOLD}Example Projects${NC}" - echo -e "${GRAY}────────────────────────────────────────────${NC}" echo "" - echo -e " we've prepared some example Plain projects for you" + echo -e " We've prepared some example ***plain projects for you" echo -e " to explore and experiment with." echo "" - echo -e " would you like to download them?" + echo -e " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to download them?${NC}" echo "" read -r -p " [Y/n]: " DOWNLOAD_EXAMPLES < /dev/tty echo "" @@ -244,19 +312,31 @@ if [ "$NONINTERACTIVE" != "1" ]; then clear fi echo "" -echo -e "${GRAY}────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}You're all set!${NC}" -echo -e "${GRAY}────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}You're all set!${NC}" echo "" -echo -e " thank you for using ${YELLOW}*codeplain!${NC}" +echo -e " ${GRAY}Thank you for using *codeplain!${NC}" echo "" -echo -e " ${BOLD}next steps:${NC}" +echo -e " ${WHITE}${BOLD}Next steps:${NC}" echo "" -echo -e " join our Discord community: ${YELLOW}https://discord.gg/cgbynb9hFq${NC}" +STEP_NUM=1 +if [ "$PLAIN_FORGE_INSTALLED" = false ]; then + echo -e " ${GRAY}${STEP_NUM}.${NC} ${GRAY}Let your agent work in specs, not code:${NC}" + echo -e " ${WHITE}${BOLD}npx plain-forge install${NC}" + echo "" + STEP_NUM=$((STEP_NUM + 1)) +fi +if [ "$PLYN_INSTALLED" = false ]; then + echo -e " ${GRAY}${STEP_NUM}.${NC} ${GRAY}Get ***plain syntax highlighting in VS Code / Cursor:${NC}" + echo -e " ${WHITE}${BOLD}https://marketplace.visualstudio.com/items?itemName=Codeplain.plyn${NC}" + echo "" + STEP_NUM=$((STEP_NUM + 1)) +fi +echo -e " ${GRAY}${STEP_NUM}.${NC} ${GRAY}Convert your spec into tested and validated code:${NC}" +echo -e " ${WHITE}${BOLD}codeplain your-project.plain${NC}" echo "" -echo -e " learn more about ${YELLOW}***plain${NC} at ${YELLOW}https://plainlang.org/${NC}" +echo -e " ${GRAY}Discord: https://discord.gg/cgbynb9hFq Docs: https://plainlang.org/${NC}" echo "" -echo -e " ${GREEN}happy development!${NC} 🚀" +echo -e " ${GRAY}Happy development!${NC} 🚀" echo "" if [ "$NONINTERACTIVE" != "1" ]; then diff --git a/install/bash/walkthrough.sh b/install/bash/walkthrough.sh index 1ca139fb..7536860c 100644 --- a/install/bash/walkthrough.sh +++ b/install/bash/walkthrough.sh @@ -13,48 +13,43 @@ NC="${NC:-\033[0m}" # Onboarding Step 1: Introduction to Plain clear echo "" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 1 of 5" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}***plain specification language intro${NC} (1/5)" echo "" -echo -e " ***plain is a language of spec-driven development that allows developers to express intent at any level of detail." +echo -e " ***plain is the language of spec-driven development that allows developers to express intent at any level of detail." echo "" -echo -e " write specs in natural language extended with additional syntax based on markdown." -echo "" -echo -e " render production-ready code with *codeplain." +echo -e " Write specs in natural language extended with additional syntax based on markdown." echo "" echo -e " A ***plain file has these key sections:" echo "" echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}***definitions***${NC} - key concepts in your app ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}***test reqs***${NC} - testing requirements ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}***functional specs***${NC} - what the app should do ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}***definitions***${NC} - key concepts in your app ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}***test reqs***${NC} - testing requirements ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}***functional specs***${NC} - what the app should do ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}" echo "" echo -e " Let's see each section in a \"hello, world\" example." echo "" -read -r -p " press [Enter] to continue..." < /dev/tty +PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...") +read -r -p "$PROMPT" < /dev/tty -# Onboarding Step 2: Functional Specification +# Onboarding Step 2: Definitions clear echo "" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 2 of 5" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}***plain specification language intro${NC} (2/5)" echo "" -echo -e " ${WHITE}${BOLD}FUNCTIONAL SPECS${NC} - what should the app do?" +echo -e " ${WHITE}${BOLD}DEFINITIONS${NC} - Definitions and descriptions of key concepts" echo "" -echo -e " This is where you describe ${GREEN}what your app should do${NC}," -echo -e " written in natural language. No code, just requirements." +echo -e " Define ${WHITE}${BOLD}reusable concepts${NC} using the ${WHITE}${BOLD}:Concept:${NC} notation." +echo -e " These become building blocks you can reference anywhere." echo "" echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}${BOLD}***definitions***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${WHITE}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" @@ -64,42 +59,41 @@ echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***functional specs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}" echo "" -echo -e " ${GREEN}▲${NC} The ${YELLOW}functional spec${NC} describes ${GREEN}what${NC} the app does." -echo -e " Here, it simply displays \"hello, world\"." +echo -e " ${GREEN}▲${NC} The ${WHITE}:App:${NC} concept is defined once and used throughout the specs." +echo -e " Concepts help keep your specs consistent and clear." echo "" -read -r -p " press [Enter] to continue..." < /dev/tty +PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...") +read -r -p "$PROMPT" < /dev/tty -# Onboarding Step 3: Definitions +# Onboarding Step 3: Implementation & Test Reqs clear echo "" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 3 of 5" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}***plain specification language intro${NC} (3/5)" echo "" -echo -e " ${WHITE}${BOLD}DEFINITIONS${NC} - definitions and descriptions of key concepts" +echo -e " ${WHITE}${BOLD}IMPLEMENTATION & TEST REQS${NC} - How to implement and test" echo "" -echo -e " Define ${GREEN}reusable concepts${NC} using the ${YELLOW}:Concept:${NC} notation." -echo -e " These become building blocks you can reference anywhere." +echo -e " Specify ${WHITE}${BOLD}implementation details${NC} and ${WHITE}${BOLD}testing requirements${NC}." +echo -e " This guides how the code should be generated and verified." echo "" echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***definitions***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${WHITE}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}${BOLD}***test reqs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${WHITE}${BOLD}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" @@ -107,22 +101,21 @@ echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}" echo "" -echo -e " ${GREEN}▲${NC} The ${YELLOW}:App:${NC} concept is defined once and used throughout the specs." -echo -e " Concepts help keep your specs consistent and clear." +echo -e " ${GREEN}▲${NC} ${WHITE}${BOLD}Implementation reqs${NC} define the language and frameworks." +echo -e " ${WHITE}${BOLD}Test reqs${NC} ensure the generated code is verified." echo "" -read -r -p " press [Enter] to continue..." < /dev/tty +PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...") +read -r -p "$PROMPT" < /dev/tty -# Onboarding Step 4: Implementation & Test Reqs +# Onboarding Step 4: Functional Specification clear echo "" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 4 of 5" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}***plain specification language intro${NC} (4/5)" echo "" -echo -e " ${WHITE}${BOLD}IMPLEMENTATION & TEST REQS${NC} - how to implement and test" +echo -e " ${WHITE}${BOLD}FUNCTIONAL SPECS${NC} - What should the app do?" echo "" -echo -e " Specify ${GREEN}implementation details${NC} and ${GREEN}testing requirements${NC}." -echo -e " This guides how the code should be generated and verified." +echo -e " This is where you describe ${WHITE}what your app should do${NC}," +echo -e " written in natural language. No code, just requirements." echo "" echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" @@ -130,46 +123,46 @@ echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***test reqs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${GREEN}${BOLD}***functional specs***${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" -echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}" +echo -e "${GRAY} │${NC} ${WHITE}${BOLD}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}" echo -e "${GRAY} │${NC} ${GRAY}│${NC}" echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}" echo "" -echo -e " ${GREEN}▲${NC} ${YELLOW}Implementation reqs${NC} define the language and frameworks." -echo -e " ${YELLOW}Test reqs${NC} ensure the generated code is verified." +echo -e " ${GREEN}▲${NC} The ${WHITE}${BOLD}functional spec${NC} describes ${WHITE}${BOLD}what the app does${NC}." +echo -e " Here, it simply displays \"hello, world\"." echo "" -read -r -p " press [Enter] to continue..." < /dev/tty +PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...") +read -r -p "$PROMPT" < /dev/tty # Onboarding Step 5: Rendering Code clear echo "" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" -echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 5 of 5" -echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}" +echo -e " ${WHITE}${BOLD}***plain specification language intro${NC} (5/5)" echo "" -echo -e " ${WHITE}${BOLD}RENDERING CODE${NC} - generate your app" +echo -e " ${WHITE}${BOLD}RENDERING CODE${NC} - Generate your app" echo "" -echo -e " Once you have a Plain file, generate code with:" +echo -e " Once you have a ***plain file, generate code with:" echo "" -echo -e " ${YELLOW}${BOLD}codeplain hello_world.plain${NC}" +echo -e " ${WHITE}${BOLD}codeplain hello_world.plain${NC}" echo "" echo -e " *codeplain will:" echo "" -echo -e " ${GREEN}1.${NC} Read your specification" -echo -e " ${GREEN}2.${NC} Generate implementation code" -echo -e " ${GREEN}3.${NC} Create and run tests to verify correctness" -echo -e " ${GREEN}4.${NC} Output production-ready code" +echo -e " ${GRAY}1. Read your specification${NC}" +echo -e " ${GRAY}2. Generate implementation code${NC}" +echo -e " ${GRAY}3. Create and run tests to verify correctness${NC}" +echo -e " ${GRAY}4. Output production-ready code${NC}" echo "" echo -e " The generated code is guaranteed to match your specs" echo -e " and pass all defined tests." echo "" -read -r -p " press [Enter] to finish..." < /dev/tty +PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to finish...") +read -r -p "$PROMPT" < /dev/tty diff --git a/install/powershell/examples.ps1 b/install/powershell/examples.ps1 index 68925ad9..2e2970a6 100644 --- a/install/powershell/examples.ps1 +++ b/install/powershell/examples.ps1 @@ -1,8 +1,9 @@ -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = 'Stop' # Brand Colors (use exported colors if available, otherwise define them) if (-not $env:YELLOW) { $YELLOW = "$([char]27)[38;2;224;255;110m" } else { $YELLOW = $env:YELLOW } if (-not $env:GREEN) { $GREEN = "$([char]27)[38;2;121;252;150m" } else { $GREEN = $env:GREEN } +if (-not $env:WHITE) { $WHITE = "$([char]27)[38;2;255;255;255m" } else { $WHITE = $env:WHITE } if (-not $env:RED) { $RED = "$([char]27)[38;2;239;68;68m" } else { $RED = $env:RED } if (-not $env:GRAY) { $GRAY = "$([char]27)[38;2;128;128;128m" } else { $GRAY = $env:GRAY } if (-not $env:BOLD) { $BOLD = "$([char]27)[1m" } else { $BOLD = $env:BOLD } @@ -14,9 +15,9 @@ $EXAMPLES_DOWNLOAD_URL = "https://github.com/Codeplain-ai/plainlang-examples/arc # Show current directory and ask for extraction path $CURRENT_DIR = Get-Location -Write-Host " current folder: ${YELLOW}${CURRENT_DIR}${NC}" +Write-Host " Current folder: ${WHITE}${CURRENT_DIR}${NC}" Write-Host "" -Write-Host " extract examples here, or enter a different path:" +Write-Host " Extract examples here, or enter a different path:" Write-Host "" $EXTRACT_PATH = Read-Host " [Enter for current, or type path]" Write-Host "" @@ -35,18 +36,18 @@ $SKIP_DOWNLOAD = $false # Check if directory exists, create if not if (-not (Test-Path $EXTRACT_PATH -PathType Container)) { - Write-Host " ${GRAY}creating directory...${NC}" + Write-Host " ${GRAY}Creating directory...${NC}" try { New-Item -ItemType Directory -Path $EXTRACT_PATH -Force | Out-Null } catch { - Write-Host " ${RED}✗${NC} failed to create directory: ${EXTRACT_PATH}" - Write-Host " ${GRAY}skipping example download.${NC}" + Write-Host " ${RED}✗ Failed to create directory: ${EXTRACT_PATH}${NC}" + Write-Host " ${GRAY}Skipping example download.${NC}" $SKIP_DOWNLOAD = $true } } if (-not $SKIP_DOWNLOAD) { - Write-Host " ${GRAY}downloading examples...${NC}" + Write-Host " ${GRAY}Downloading examples...${NC}" $TEMP_ZIP = Join-Path ([System.IO.Path]::GetTempPath()) "plainlang-examples.zip" @@ -54,7 +55,7 @@ if (-not $SKIP_DOWNLOAD) { Invoke-WebRequest -Uri $EXAMPLES_DOWNLOAD_URL -OutFile $TEMP_ZIP -UseBasicParsing if (Test-Path $TEMP_ZIP) { - Write-Host " ${GRAY}extracting to ${EXTRACT_PATH}...${NC}" + Write-Host " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}" try { Expand-Archive -Path $TEMP_ZIP -DestinationPath $EXTRACT_PATH -Force @@ -76,24 +77,33 @@ if (-not $SKIP_DOWNLOAD) { Remove-Item -Path $GITIGNORE_PATH -Force } + Clear-Host Write-Host "" - Write-Host " ${GREEN}✓${NC} examples downloaded successfully!" + Write-Host " ${GREEN}✓ Examples downloaded successfully!${NC}" Write-Host "" - Write-Host " examples are in: ${YELLOW}${EXTRACTED_DIR}${NC}" + Write-Host " ${GRAY}Examples are in: ${EXTRACTED_DIR}${NC}" + Write-Host "" + Write-Host " ${WHITE}${BOLD}Try the hello, world example:${NC}" + Write-Host "" + Write-Host " ${GRAY}Example folder:${NC} ${WHITE}cd ${EXTRACTED_DIR}\hello-world\python${NC}" + Write-Host "" + Write-Host " ${GRAY}Render the example:${NC} ${WHITE}codeplain hello-world-python.plain${NC}" + Write-Host "" + Write-Host " ${GRAY}See hello-world/python/README.md for details.${NC}" Write-Host "" } catch { - Write-Host " ${RED}✗${NC} failed to extract examples." + Write-Host " ${RED}✗ Failed to extract examples.${NC}" } Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue } else { - Write-Host " ${RED}✗${NC} failed to download examples." + Write-Host " ${RED}✗ Failed to download examples.${NC}" } } catch { - Write-Host " ${RED}✗${NC} failed to download examples." + Write-Host " ${RED}✗ Failed to download examples.${NC}" Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue } Write-Host "" - Read-Host " press [Enter] to continue..." + Read-Host " Press ${WHITE}[Enter]${NC} to continue..." } diff --git a/install/powershell/install.ps1 b/install/powershell/install.ps1 index 2dd8f537..75a4b257 100644 --- a/install/powershell/install.ps1 +++ b/install/powershell/install.ps1 @@ -4,7 +4,7 @@ $ErrorActionPreference = 'Stop' # prompts and Clear-Host calls. Same env var name as install.sh. $nonInteractive = ($env:CODEPLAIN_INSTALL_NONINTERACTIVE -eq "1") if ($nonInteractive) { - Write-Host "running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)" + Write-Host "Running in non-interactive mode (CODEPLAIN_INSTALL_NONINTERACTIVE=1)" } # Base URL for additional scripts @@ -42,11 +42,11 @@ $env:BOLD = $BOLD $env:NC = $NC if (-not $nonInteractive) { Clear-Host } -Write-Host "started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..." +Write-Host "Started ${YELLOW}${BOLD}*codeplain CLI${NC} installation..." # Install uv if not present function Install-Uv { - Write-Host "installing uv package manager..." + Write-Host "Installing uv package manager..." if ($IsWindows -or ($env:OS -eq "Windows_NT")) { irm https://astral.sh/uv/install.ps1 | iex $env:Path = [Environment]::GetEnvironmentVariable('Path', 'User') + ';' + [Environment]::GetEnvironmentVariable('Path', 'Machine') @@ -78,7 +78,7 @@ $codeplainLine = $uvOutput | Where-Object { $_ -match '^codeplain' } | Select-Ob if ($codeplainLine) { $currentVersion = ($codeplainLine -replace 'codeplain v', '').Trim() Write-Host "${GRAY}codeplain ${currentVersion} is already installed.${NC}" - Write-Host "upgrading to latest version..." + Write-Host "Upgrading to latest version..." Write-Host "" try { @@ -98,7 +98,7 @@ if ($codeplainLine) { Write-Host "${GREEN}✓${NC} codeplain upgraded from ${currentVersion} to ${newVersion}!" } } else { - Write-Host "installing codeplain...${NC}" + Write-Host "Installing codeplain...${NC}" Write-Host "" uv tool install codeplain if (-not $nonInteractive) { Clear-Host } @@ -127,18 +127,18 @@ Write-Host "" $skipApiKeySetup = $false if ($env:CODEPLAIN_API_KEY) { if ($nonInteractive) { - Write-Host "${GREEN}✓${NC} using existing CODEPLAIN_API_KEY (non-interactive mode)." + Write-Host "${GREEN}✓${NC} Using existing CODEPLAIN_API_KEY (non-interactive mode)." $skipApiKeySetup = $true } else { - Write-Host " you already have an API key configured." + Write-Host " You already have an API key configured." Write-Host "" - Write-Host " would you like to log in and get a new one?" + Write-Host " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to log in and get a new one?${NC}" Write-Host "" $getNewKey = Read-Host " [y/N]" Write-Host "" if ($getNewKey -notmatch '^[Yy]$') { - Write-Host "${GREEN}✓${NC} using existing API key." + Write-Host "${GREEN}✓${NC} Using existing API key." $skipApiKeySetup = $true } } @@ -147,11 +147,11 @@ if ($env:CODEPLAIN_API_KEY) { $apiKey = $null if (-not $skipApiKeySetup) { if ($nonInteractive) { - Write-Host "${GRAY}no CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}" + Write-Host "${GRAY}No CODEPLAIN_API_KEY set; skipping key setup (non-interactive mode).${NC}" } else { - Write-Host "go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key." + Write-Host "Go to ${YELLOW}https://platform.codeplain.ai${NC} and sign up to get your API key." Write-Host "" - $apiKey = Read-Host "paste your API key here" + $apiKey = Read-Host "Paste your API key here" Write-Host "" } } @@ -159,7 +159,7 @@ if (-not $skipApiKeySetup) { if ($skipApiKeySetup) { # API key already set, nothing to do } elseif (-not $apiKey) { - Write-Host "${GRAY}no API key provided. you can set it later with:${NC}" + Write-Host "${GRAY}No API key provided. You can set it later with:${NC}" Write-Host ' $env:CODEPLAIN_API_KEY = "your_api_key"' } else { # Set for current session @@ -172,10 +172,6 @@ if ($skipApiKeySetup) { # ASCII Art Welcome if (-not $nonInteractive) { Clear-Host } -Write-Host "" -Write-Host "${NC}" -Write-Host "${GRAY}────────────────────────────────────────────${NC}" -Write-Host "" Write-Host @' _ _ _ ___ ___ __| | ___ _ __ | | __ _(_)_ __ @@ -185,19 +181,16 @@ Write-Host @' |_| '@ Write-Host "" -Write-Host "${GREEN}✓${NC} Sign in successful." -Write-Host "" -Write-Host " ${YELLOW}welcome to *codeplain!${NC}" +Write-Host "${GREEN}✓ Sign in successful.${NC}" Write-Host "" -Write-Host " spec-driven, production-ready code generation" +Write-Host " ${WHITE}Welcome to *codeplain!${NC}" Write-Host "" -Write-Host "" -Write-Host "${GRAY}────────────────────────────────────────────${NC}" +Write-Host " ${GRAY}Spec-driven, production-ready code generation${NC}" Write-Host "" if ($nonInteractive) { $walkthroughChoice = "n" } else { - Write-Host " would you like to get a quick intro to ***plain specification language?" + Write-Host " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to get a quick intro to ***plain specification language?${NC}" Write-Host "" $walkthroughChoice = Read-Host " [Y/n]" Write-Host "" @@ -244,20 +237,91 @@ if ($walkthroughChoice -notmatch '^[Nn]$') { Invoke-SubScript "walkthrough.ps1" } +# Install plain-forge step +if ($nonInteractive) { + $installPlainForge = "n" +} else { + Clear-Host + Write-Host "" + Write-Host " ${YELLOW}${BOLD}plain-forge${NC}" + Write-Host "" + Write-Host " plain-forge plugs into your AI coding agent (Claude Code, Codex," + Write-Host " ForgeCode, OpenCode, ...) and turns a conversation into a" + Write-Host " complete ***plain spec, keeping it maintained as you grow it." + Write-Host "" + Write-Host " ${GRAY}Read more: https://github.com/Codeplain-ai/plain-forge${NC}" + Write-Host "" + Write-Host " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to install it now?${NC}" + Write-Host "" + $installPlainForge = Read-Host " [Y/n]" + Write-Host "" +} + +$plainForgeInstalled = $false +if ($installPlainForge -notmatch '^[Nn]$') { + if (Get-Command npx -ErrorAction SilentlyContinue) { + npx plain-forge install + $plainForgeInstalled = $true + Write-Host "" + } else { + Write-Host "${GRAY}npx not found. Install Node.js, then run:${NC}" + Write-Host " npx plain-forge install" + Write-Host "" + } +} + +# Install plyn editor extension step +$editorCmds = @() +if (Get-Command cursor -ErrorAction SilentlyContinue) { $editorCmds += [pscustomobject]@{ Cmd = "cursor"; Name = "Cursor" } } +if (Get-Command code -ErrorAction SilentlyContinue) { $editorCmds += [pscustomobject]@{ Cmd = "code"; Name = "VS Code" } } + +if ($nonInteractive) { + $installPlyn = "n" +} else { + Clear-Host + Write-Host "" + Write-Host " ${YELLOW}${BOLD}plyn Editor Extension${NC}" + Write-Host "" + Write-Host " plyn adds ***plain syntax highlighting to VS Code and Cursor." + Write-Host "" + if ($editorCmds.Count -gt 0) { + $editorNames = ($editorCmds | ForEach-Object { $_.Name }) -join ", " + Write-Host " Detected ${editorNames}." + Write-Host "" + Write-Host " ${YELLOW}?${NC} ${WHITE}${BOLD}Install the extension now?${NC}" + Write-Host "" + $installPlyn = Read-Host " [Y/n]" + Write-Host "" + } else { + Write-Host " Install it manually from:" + Write-Host " ${YELLOW}https://marketplace.visualstudio.com/items?itemName=Codeplain.plyn${NC}" + Write-Host "" + $installPlyn = "n" + } +} + +$plynInstalled = $false +if ($editorCmds.Count -gt 0 -and $installPlyn -notmatch '^[Nn]$') { + foreach ($editor in $editorCmds) { + & $editor.Cmd --install-extension Codeplain.plyn + Write-Host "${GREEN}✓${NC} plyn installed for $($editor.Name)" + } + $plynInstalled = $true + Write-Host "" +} + # Download examples step if ($nonInteractive) { $downloadExamples = "n" } else { Clear-Host Write-Host "" - Write-Host "${GRAY}────────────────────────────────────────────${NC}" Write-Host " ${YELLOW}${BOLD}Example Projects${NC}" - Write-Host "${GRAY}────────────────────────────────────────────${NC}" Write-Host "" - Write-Host " we've prepared some example Plain projects for you" + Write-Host " We've prepared some example ***plain projects for you" Write-Host " to explore and experiment with." Write-Host "" - Write-Host " would you like to download them?" + Write-Host " ${YELLOW}?${NC} ${WHITE}${BOLD}Would you like to download them?${NC}" Write-Host "" $downloadExamples = Read-Host " [Y/n]" Write-Host "" @@ -271,19 +335,31 @@ if ($downloadExamples -notmatch '^[Nn]$') { # Final message if (-not $nonInteractive) { Clear-Host } Write-Host "" -Write-Host "${GRAY}────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}You're all set!${NC}" -Write-Host "${GRAY}────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}You're all set!${NC}" Write-Host "" -Write-Host " thank you for using ${YELLOW}*codeplain!${NC}" +Write-Host " ${GRAY}Thank you for using *codeplain!${NC}" Write-Host "" -Write-Host " ${BOLD}next steps:${NC}" +Write-Host " ${WHITE}${BOLD}Next steps:${NC}" Write-Host "" -Write-Host " join our Discord community: ${YELLOW}https://discord.gg/cgbynb9hFq${NC}" +$stepNum = 1 +if (-not $plainForgeInstalled) { + Write-Host " ${GRAY}${stepNum}.${NC} ${GRAY}Let your agent work in specs, not code:${NC}" + Write-Host " ${WHITE}${BOLD}npx plain-forge install${NC}" + Write-Host "" + $stepNum++ +} +if (-not $plynInstalled) { + Write-Host " ${GRAY}${stepNum}.${NC} ${GRAY}Get ***plain syntax highlighting in VS Code / Cursor:${NC}" + Write-Host " ${WHITE}${BOLD}https://marketplace.visualstudio.com/items?itemName=Codeplain.plyn${NC}" + Write-Host "" + $stepNum++ +} +Write-Host " ${GRAY}${stepNum}.${NC} ${GRAY}Convert your spec into tested and validated code:${NC}" +Write-Host " ${WHITE}${BOLD}codeplain your-project.plain${NC}" Write-Host "" -Write-Host " learn more about ${YELLOW}***plain${NC} at ${YELLOW}https://plainlang.org/${NC}" +Write-Host " ${GRAY}Discord: https://discord.gg/cgbynb9hFq Docs: https://plainlang.org/${NC}" Write-Host "" -Write-Host " ${GREEN}happy development!${NC} 🚀" +Write-Host " ${GRAY}Happy development!${NC} 🚀" Write-Host "" # Refresh environment for this session diff --git a/install/powershell/walkthrough.ps1 b/install/powershell/walkthrough.ps1 index 21810cd7..2fcbe93e 100644 --- a/install/powershell/walkthrough.ps1 +++ b/install/powershell/walkthrough.ps1 @@ -1,4 +1,4 @@ -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = 'Stop' # Brand Colors (use exported colors if available, otherwise define them) if (-not $env:YELLOW) { $YELLOW = "$([char]27)[38;2;224;255;110m" } else { $YELLOW = $env:YELLOW } @@ -11,48 +11,42 @@ if (-not $env:NC) { $NC = "$([char]27)[0m" } else # Onboarding Step 1: Introduction to Plain Clear-Host Write-Host "" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 1 of 5" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}***plain specification language intro${NC} (1/5)" Write-Host "" -Write-Host " ***plain is a language of spec-driven development that allows developers to express intent at any level of detail." +Write-Host " ***plain is the language of spec-driven development that allows developers to express intent at any level of detail." Write-Host "" -Write-Host " write specs in natural language extended with additional syntax based on markdown." -Write-Host "" -Write-Host " render production-ready code with *codeplain." +Write-Host " Write specs in natural language extended with additional syntax based on markdown." Write-Host "" Write-Host " A ***plain file has these key sections:" Write-Host "" Write-Host "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}***definitions***${NC} - key concepts in your app ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}***test reqs***${NC} - testing requirements ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}***functional specs***${NC} - what the app should do ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}***definitions***${NC} - key concepts in your app ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}***test reqs***${NC} - testing requirements ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}***functional specs***${NC} - what the app should do ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} └────────────────────────────────────────────────────────┘${NC}" Write-Host "" Write-Host " Let's see each section in a `"hello, world`" example." Write-Host "" -Read-Host " press [Enter] to continue..." +Read-Host " Press ${WHITE}[Enter]${NC} to continue..." -# Onboarding Step 2: Functional Specification +# Onboarding Step 2: Definitions Clear-Host Write-Host "" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 2 of 5" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}***plain specification language intro${NC} (2/5)" Write-Host "" -Write-Host " ${WHITE}${BOLD}FUNCTIONAL SPECS${NC} - what should the app do?" +Write-Host " ${WHITE}${BOLD}DEFINITIONS${NC} - Definitions and descriptions of key concepts" Write-Host "" -Write-Host " This is where you describe ${GREEN}what your app should do${NC}," -Write-Host " written in natural language. No code, just requirements." +Write-Host " Define ${WHITE}${BOLD}reusable concepts${NC} using the ${WHITE}${BOLD}:Concept:${NC} notation." +Write-Host " These become building blocks you can reference anywhere." Write-Host "" Write-Host "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}***definitions***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${WHITE}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" @@ -62,42 +56,40 @@ Write-Host "${GRAY} │${NC} ${GRAY}***test reqs***${NC} Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}${BOLD}***functional specs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}- :App: should display `"hello, world`".${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}- :App: should display `"hello, world`".${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} └────────────────────────────────────────────────────────┘${NC}" Write-Host "" -Write-Host " ${GREEN}▲${NC} The ${YELLOW}functional spec${NC} describes ${GREEN}what${NC} the app does." -Write-Host " Here, it simply displays `"hello, world`"." +Write-Host " ${GREEN}▲${NC} The ${WHITE}:App:${NC} concept is defined once and used throughout the specs." +Write-Host " Concepts help keep your specs consistent and clear." Write-Host "" -Read-Host " press [Enter] to continue..." +Read-Host " Press ${WHITE}[Enter]${NC} to continue..." -# Onboarding Step 3: Definitions +# Onboarding Step 3: Implementation & Test Reqs Clear-Host Write-Host "" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 3 of 5" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}***plain specification language intro${NC} (3/5)" Write-Host "" -Write-Host " ${WHITE}${BOLD}DEFINITIONS${NC} - definitions and descriptions of key concepts" +Write-Host " ${WHITE}${BOLD}IMPLEMENTATION & TEST REQS${NC} - How to implement and test" Write-Host "" -Write-Host " Define ${GREEN}reusable concepts${NC} using the ${YELLOW}:Concept:${NC} notation." -Write-Host " These become building blocks you can reference anywhere." +Write-Host " Specify ${WHITE}${BOLD}implementation details${NC} and ${WHITE}${BOLD}testing requirements${NC}." +Write-Host " This guides how the code should be generated and verified." Write-Host "" Write-Host "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}${BOLD}***definitions***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${WHITE}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}***test reqs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${WHITE}${BOLD}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" @@ -105,22 +97,20 @@ Write-Host "${GRAY} │${NC} ${GRAY}- :App: should display `"hello, world`".${ Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} └────────────────────────────────────────────────────────┘${NC}" Write-Host "" -Write-Host " ${GREEN}▲${NC} The ${YELLOW}:App:${NC} concept is defined once and used throughout the specs." -Write-Host " Concepts help keep your specs consistent and clear." +Write-Host " ${GREEN}▲${NC} ${WHITE}${BOLD}Implementation reqs${NC} define the language and frameworks." +Write-Host " ${WHITE}${BOLD}Test reqs${NC} ensure the generated code is verified." Write-Host "" -Read-Host " press [Enter] to continue..." +Read-Host " Press ${WHITE}[Enter]${NC} to continue..." -# Onboarding Step 4: Implementation & Test Reqs +# Onboarding Step 4: Functional Specification Clear-Host Write-Host "" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 4 of 5" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}***plain specification language intro${NC} (4/5)" Write-Host "" -Write-Host " ${WHITE}${BOLD}IMPLEMENTATION & TEST REQS${NC} - how to implement and test" +Write-Host " ${WHITE}${BOLD}FUNCTIONAL SPECS${NC} - What should the app do?" Write-Host "" -Write-Host " Specify ${GREEN}implementation details${NC} and ${GREEN}testing requirements${NC}." -Write-Host " This guides how the code should be generated and verified." +Write-Host " This is where you describe ${WHITE}what your app should do${NC}," +Write-Host " written in natural language. No code, just requirements." Write-Host "" Write-Host "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" @@ -128,46 +118,44 @@ Write-Host "${GRAY} │${NC} ${GRAY}***definitions***${NC} Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${YELLOW}${BOLD}***test reqs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${GREEN}${BOLD}***functional specs***${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" -Write-Host "${GRAY} │${NC} ${GRAY}- :App: should display `"hello, world`".${NC} ${GRAY}│${NC}" +Write-Host "${GRAY} │${NC} ${WHITE}${BOLD}- :App: should display `"hello, world`".${NC} ${GRAY}│${NC}" Write-Host "${GRAY} │${NC} ${GRAY}│${NC}" Write-Host "${GRAY} └────────────────────────────────────────────────────────┘${NC}" Write-Host "" -Write-Host " ${GREEN}▲${NC} ${YELLOW}Implementation reqs${NC} define the language and frameworks." -Write-Host " ${YELLOW}Test reqs${NC} ensure the generated code is verified." +Write-Host " ${GREEN}▲${NC} The ${WHITE}${BOLD}functional spec${NC} describes ${WHITE}${BOLD}what the app does${NC}." +Write-Host " Here, it simply displays `"hello, world`"." Write-Host "" -Read-Host " press [Enter] to continue..." +Read-Host " Press ${WHITE}[Enter]${NC} to continue..." # Onboarding Step 5: Rendering Code Clear-Host Write-Host "" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" -Write-Host " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 5 of 5" -Write-Host "${GRAY}─────────────────────────────────────────────────────────${NC}" +Write-Host " ${WHITE}${BOLD}***plain specification language intro${NC} (5/5)" Write-Host "" -Write-Host " ${WHITE}${BOLD}RENDERING CODE${NC} - generate your app" +Write-Host " ${WHITE}${BOLD}RENDERING CODE${NC} - Generate your app" Write-Host "" -Write-Host " Once you have a Plain file, generate code with:" +Write-Host " Once you have a ***plain file, generate code with:" Write-Host "" -Write-Host " ${YELLOW}${BOLD}codeplain hello_world.plain${NC}" +Write-Host " ${WHITE}${BOLD}codeplain hello_world.plain${NC}" Write-Host "" Write-Host " *codeplain will:" Write-Host "" -Write-Host " ${GREEN}1.${NC} Read your specification" -Write-Host " ${GREEN}2.${NC} Generate implementation code" -Write-Host " ${GREEN}3.${NC} Create and run tests to verify correctness" -Write-Host " ${GREEN}4.${NC} Output production-ready code" +Write-Host " ${GRAY}1. Read your specification${NC}" +Write-Host " ${GRAY}2. Generate implementation code${NC}" +Write-Host " ${GRAY}3. Create and run tests to verify correctness${NC}" +Write-Host " ${GRAY}4. Output production-ready code${NC}" Write-Host "" Write-Host " The generated code is guaranteed to match your specs" Write-Host " and pass all defined tests." Write-Host "" -Read-Host " press [Enter] to finish..." +Read-Host " Press ${WHITE}[Enter]${NC} to finish..."