diff options
Diffstat (limited to '')
| -rw-r--r-- | .lush/init.lua | 35 | ||||
| -rw-r--r-- | .lush/scripts/example.lua | 5 | ||||
| -rw-r--r-- | install.sh | 7 | ||||
| -rw-r--r-- | src/lua_api.c | 51 | ||||
| -rw-r--r-- | src/lua_api.h | 1 | ||||
| -rw-r--r-- | src/lush.c | 114 | ||||
| -rw-r--r-- | src/lush.h | 5 | ||||
| -rw-r--r-- | vgcore.250513 | bin | 0 -> 7970816 bytes |
8 files changed, 180 insertions, 38 deletions
diff --git a/.lush/init.lua b/.lush/init.lua new file mode 100644 index 0000000..26fe71e --- /dev/null +++ b/.lush/init.lua @@ -0,0 +1,35 @@ +--[[ +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +]] + +-- This file is your init.lua. It will be automatically executed each time you open +-- a new session of Lunar Shell. + +-- Setting environment variables +local path = lush.getenv("HOME") .. "/bin:" .. lush.getenv("PATH") +lush.setenv("PATH", path) + +-- the prompt can be customized here too +-- %u is username, %h is hostname, %w is current working directory +lush.setPrompt("[%u@%h: %w]") +-- any global functions that accept either no parameters or just an array of args +-- will be read in and stored as built in commands for the shell +function my_command(args) + print("my custom command") +end + +-- all functions from the Lunar Shell Lua API are available to you to +-- customize your startup however you want diff --git a/.lush/scripts/example.lua b/.lush/scripts/example.lua index 4d0b8fa..c60f99b 100644 --- a/.lush/scripts/example.lua +++ b/.lush/scripts/example.lua @@ -84,7 +84,10 @@ print("Most recent history: " .. lush.lastHistory()) print("Most recent history indexed: " .. lush.getHistory(1)) -- you can set environment variables using putenv -lush.putenv("EXAMPLE=Lunar Shell Example") +lush.setenv("EXAMPLE", "Lunar Shell Example") -- you can get an environment variable using getenv print("Value of EXAMPLE: " .. lush.getenv("EXAMPLE")) + +-- you can unset an environment variable with unsetenv +lush.unsetenv("EXAMPLE") @@ -51,7 +51,12 @@ rm premake.tar.gz premake5 gmake make -cp -rf ./.lush ~/ +if [ ! -d ~/.lush ]; then + cp -rf ./.lush ~/ +fi + +# always update example +cp -f ./.lush/scripts/example.lua ~/.lush/scripts/example.lua # Install the new shell binary to a temporary location sudo cp ./bin/Debug/lush/lush /usr/bin/lush.new diff --git a/src/lua_api.c b/src/lua_api.c index e28d7c1..2f967e6 100644 --- a/src/lua_api.c +++ b/src/lua_api.c @@ -29,7 +29,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #include <sys/stat.h> #include <unistd.h> -// global for checking if debug_mode is toggled +// globals static bool debug_mode = false; // -- script execution -- @@ -56,7 +56,7 @@ void lua_load_script(lua_State *L, const char *script, char **args) { } } // add args global if args were passed - if (args[0] != NULL) { + if (args != NULL && args[0] != NULL) { lua_newtable(L); for (int i = 0; args[i]; i++) { lua_pushstring(L, args[i]); @@ -79,6 +79,12 @@ void lua_load_script(lua_State *L, const char *script, char **args) { } } +void lua_run_init(lua_State *L) { + char script_path[64]; + snprintf(script_path, sizeof(script_path), ".lush/%s", "init.lua"); + lua_load_script(L, script_path, NULL); +} + // -- C funtions -- static int execute_command(lua_State *L, const char *line) { int status = 0; @@ -284,9 +290,38 @@ static int l_get_env(lua_State *L) { return 1; } -static int l_put_env(lua_State *L) { +static int l_set_env(lua_State *L) { + const char *env_name = luaL_checkstring(L, 1); + const char *env_value = luaL_checkstring(L, 2); + setenv(env_name, env_value, 1); + return 0; +} + +static int l_unset_env(lua_State *L) { const char *env = luaL_checkstring(L, 1); - putenv((char *)env); + unsetenv(env); + return 0; +} + +static int l_set_prompt(lua_State *L) { + const char *format = luaL_checkstring(L, 1); + if (format == NULL) { + perror("string format not passed"); + return 0; + } + + // free old prompt format if necessary + if (prompt_format) { + free(prompt_format); + } + + prompt_format = malloc(strlen(format) + 1); + + if (prompt_format) { + strcpy(prompt_format, format); + } else { + perror("malloc failed"); + } return 0; } @@ -320,8 +355,12 @@ void lua_register_api(lua_State *L) { lua_setfield(L, -2, "getHistory"); lua_pushcfunction(L, l_get_env); lua_setfield(L, -2, "getenv"); - lua_pushcfunction(L, l_put_env); - lua_setfield(L, -2, "putenv"); + lua_pushcfunction(L, l_set_env); + lua_setfield(L, -2, "setenv"); + lua_pushcfunction(L, l_unset_env); + lua_setfield(L, -2, "unsetenv"); + lua_pushcfunction(L, l_set_prompt); + lua_setfield(L, -2, "setPrompt"); // set the table as global lua_setglobal(L, "lush"); } diff --git a/src/lua_api.h b/src/lua_api.h index c9f61ab..9027040 100644 --- a/src/lua_api.h +++ b/src/lua_api.h @@ -21,6 +21,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #include <lua.h> void lua_load_script(lua_State *L, const char *script, char **args); +void lua_run_init(lua_State *L); void lua_register_api(lua_State *L); #endif @@ -40,6 +40,9 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #define BUFFER_SIZE 1024 +// initialize prompt format +char *prompt_format = NULL; + // -- builtin functions -- char *builtin_strs[] = {"cd", "help", "exit", "time"}; @@ -163,10 +166,67 @@ static int get_terminal_width() { return w.ws_col; } +static size_t get_prompt_len(const char *format, const char *username, + const char *hostname, const char *cwd) { + size_t prompt_len = 0; + + while (*format) { + if (strncmp(format, "%u", 2) == 0) { + prompt_len += strlen(username); + format += 2; + } else if (strncmp(format, "%h", 2) == 0) { + prompt_len += strlen(hostname); + format += 2; + } else if (strncmp(format, "%w", 2) == 0) { + prompt_len += strlen(cwd); + format += 2; + } else { + prompt_len++; + format++; + } + } + return prompt_len; +} + +static char *format_prompt_string(const char *input, const char *username, + const char *hostname, const char *cwd) { + // Calculate the size of the new string + size_t new_size = get_prompt_len(input, username, hostname, cwd) + 1; + + // Allocate memory for the new string + char *result = (char *)malloc(new_size); + if (!result) { + return NULL; // Handle memory allocation failure + } + + // Replace placeholders in the input string and build the result string + char *dest = result; + while (*input) { + if (strncmp(input, "%u", 2) == 0) { + strcpy(dest, username); + dest += strlen(username); + input += 2; + } else if (strncmp(input, "%h", 2) == 0) { + strcpy(dest, hostname); + dest += strlen(hostname); + input += 2; + } else if (strncmp(input, "%w", 2) == 0) { + strcpy(dest, cwd); + dest += strlen(cwd); + input += 2; + } else { + *dest++ = *input++; + } + } + + *dest = '\0'; // Null-terminate the result string + return result; +} + static char *get_prompt() { char *username = getenv("USER"); - char device_name[256]; - gethostname(device_name, sizeof(device_name)); + char hostname[256]; + gethostname(hostname, sizeof(hostname)); char *cwd = getcwd(NULL, 0); // Replace /home/<user> with ~ @@ -182,12 +242,20 @@ static char *get_prompt() { prompt_cwd = strdup(cwd); } - // Print the prompt - size_t prompt_len = - strlen(prompt_cwd) + strlen(username) + strlen(device_name) + 6; - char *prompt = (char *)malloc(prompt_len); - snprintf(prompt, prompt_len, "[%s@%s:%s]", username, device_name, - prompt_cwd); + // get the prompt if no format in init.lua + if (prompt_format == NULL) { + size_t prompt_len = + strlen(prompt_cwd) + strlen(username) + strlen(hostname) + 6; + char *prompt = (char *)malloc(prompt_len); + snprintf(prompt, prompt_len, "[%s@%s:%s]", username, hostname, + prompt_cwd); + free(cwd); + return prompt; + } + + // get formatted prompt + char *prompt = + format_prompt_string(prompt_format, username, hostname, prompt_cwd); free(cwd); return prompt; @@ -581,9 +649,11 @@ int main(int argc, char *argv[]) { #endif return 0; } + // init lua state lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_register_api(L); + lua_run_init(L); // eat ^C in main struct sigaction sa; sa.sa_handler = SIG_IGN; @@ -594,28 +664,9 @@ int main(int argc, char *argv[]) { int status = 0; while (true) { // Prompt - char *username = getenv("USER"); - char device_name[256]; - gethostname(device_name, sizeof(device_name)); - char *cwd = getcwd(NULL, 0); - - // Replace /home/<user> with ~ - char *home_prefix = "/home/"; - size_t home_len = strlen(home_prefix) + strlen(username); - char *prompt_cwd; - if (strncmp(cwd, home_prefix, strlen(home_prefix)) == 0 && - strncmp(cwd + strlen(home_prefix), username, strlen(username)) == - 0) { - prompt_cwd = malloc(strlen(cwd) - home_len + - 2); // 1 for ~ and 1 for null terminator - snprintf(prompt_cwd, strlen(cwd) - home_len + 2, "~%s", - cwd + home_len); - } else { - prompt_cwd = strdup(cwd); - } + char *prompt = get_prompt(); - // Print the prompt - printf("[%s@%s:%s] ", username, device_name, prompt_cwd); + printf("%s ", prompt); char *line = lush_read_line(); lush_push_history(line); printf("\n"); @@ -635,11 +686,14 @@ int main(int argc, char *argv[]) { free(args[i]); } // add last line to history - free(cwd); + free(prompt); free(args); free(commands); free(line); } lua_close(L); + if (prompt_format != NULL) + free(prompt_format); + return 0; } @@ -37,4 +37,9 @@ char ***lush_split_args(char **commands, int *status); void lush_execute_command(char **args, int input_fd, int output_fd); int lush_execute_pipeline(char ***commands, int num_commands); +void lush_format_prompt(const char *prompt_format); + +// format spec for the prompt +extern char *prompt_format; + #endif // LUSH_H diff --git a/vgcore.250513 b/vgcore.250513 Binary files differnew file mode 100644 index 0000000..85ad236 --- /dev/null +++ b/vgcore.250513 |
