aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar BanceDev 2024-09-09 16:17:08 -0400
committerGravatar BanceDev 2024-09-09 16:17:08 -0400
commit521316d09b39a410d7e797efa176371e31a3a57e (patch)
treebb0c6bb5a9df1280fceb483983e2328ee87c0da0
parentbugfix to inline backspace and delete on multiline buffer (diff)
add aliasing to init.lua
-rw-r--r--.gitignore1
-rw-r--r--.lush/init.lua9
-rw-r--r--compile_commands.json58
-rw-r--r--lib/hashmap/hashmap.c69
-rw-r--r--lib/hashmap/hashmap.h38
-rw-r--r--premake5.lua4
-rw-r--r--src/lua_api.c9
-rw-r--r--src/lush.c81
-rw-r--r--src/lush.h3
9 files changed, 258 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore
index c297f50..a861fad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,3 @@ Makefile
bin
obj
.cache
-vgcore.250513
diff --git a/.lush/init.lua b/.lush/init.lua
index 26fe71e..5446dd0 100644
--- a/.lush/init.lua
+++ b/.lush/init.lua
@@ -25,11 +25,10 @@ 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
+
+-- aliases can be defined using the alias method by passing the alias name
+-- and the command to execute with the alias
+lush.alias("h", "help")
-- all functions from the Lunar Shell Lua API are available to you to
-- customize your startup however you want
diff --git a/compile_commands.json b/compile_commands.json
index 5ba9a1e..1edddc2 100644
--- a/compile_commands.json
+++ b/compile_commands.json
@@ -5,14 +5,66 @@
"-DLUSH_VERSION=\"0.0.1\"",
"-DDEBUG",
"-I/usr/include/lua5.4",
+ "-Ilib/hashmap",
+ "-g",
+ "-c",
+ "-o",
+ "obj/Debug/hashmap.o",
+ "lib/hashmap/hashmap.c"
+ ],
+ "directory": "/home/lanceb/lush",
+ "file": "/home/lanceb/lush/lib/hashmap/hashmap.c",
+ "output": "/home/lanceb/lush/obj/Debug/hashmap.o"
+ },
+ {
+ "arguments": [
+ "/usr/bin/cc",
+ "-DLUSH_VERSION=\"0.0.1\"",
+ "-DDEBUG",
+ "-I/usr/include/lua5.4",
+ "-Ilib/hashmap",
+ "-g",
+ "-c",
+ "-o",
+ "obj/Debug/history.o",
+ "src/history.c"
+ ],
+ "directory": "/home/lanceb/lush",
+ "file": "/home/lanceb/lush/src/history.c",
+ "output": "/home/lanceb/lush/obj/Debug/history.o"
+ },
+ {
+ "arguments": [
+ "/usr/bin/cc",
+ "-DLUSH_VERSION=\"0.0.1\"",
+ "-DDEBUG",
+ "-I/usr/include/lua5.4",
+ "-Ilib/hashmap",
+ "-g",
+ "-c",
+ "-o",
+ "obj/Debug/lua_api.o",
+ "src/lua_api.c"
+ ],
+ "directory": "/home/lanceb/lush",
+ "file": "/home/lanceb/lush/src/lua_api.c",
+ "output": "/home/lanceb/lush/obj/Debug/lua_api.o"
+ },
+ {
+ "arguments": [
+ "/usr/bin/cc",
+ "-DLUSH_VERSION=\"0.0.1\"",
+ "-DDEBUG",
+ "-I/usr/include/lua5.4",
+ "-Ilib/hashmap",
"-g",
"-c",
"-o",
"obj/Debug/lush.o",
"src/lush.c"
],
- "directory": "/home/lanceb/projects/lush",
- "file": "/home/lanceb/projects/lush/src/lush.c",
- "output": "/home/lanceb/projects/lush/obj/Debug/lush.o"
+ "directory": "/home/lanceb/lush",
+ "file": "/home/lanceb/lush/src/lush.c",
+ "output": "/home/lanceb/lush/obj/Debug/lush.o"
}
]
diff --git a/lib/hashmap/hashmap.c b/lib/hashmap/hashmap.c
new file mode 100644
index 0000000..cfc112c
--- /dev/null
+++ b/lib/hashmap/hashmap.c
@@ -0,0 +1,69 @@
+/*
+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.
+*/
+
+#include "hashmap.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+hashmap_t *hm_new_hashmap() {
+ hashmap_t *this = malloc(sizeof(hashmap_t));
+ this->cap = 8;
+ this->len = 0;
+ // null all pointers in list
+ this->list = calloc((this->cap), sizeof(map_pair_t *));
+ return this;
+}
+
+unsigned int hm_hashcode(hashmap_t *this, char *key) {
+ unsigned int code;
+ for (code = 0; *key != '\0'; key++) {
+ code = *key + 31 * code;
+ }
+
+ return code % (this->cap);
+}
+
+char *hm_get(hashmap_t *this, char *key) {
+ map_pair_t *current;
+ for (current = this->list[hm_hashcode(this, key)]; current;
+ current = current->next) {
+ if (strcmp(current->key, key) == 0) {
+ return current->val;
+ }
+ }
+ // the key is not found
+ return NULL;
+}
+
+void hm_set(hashmap_t *this, char *key, char *val) {
+ unsigned int idx = hm_hashcode(this, key);
+ map_pair_t *current;
+ for (current = this->list[idx]; current; current = current->next) {
+ if (strcmp(current->key, key) == 0) {
+ current->val = val;
+ return;
+ }
+ }
+
+ map_pair_t *p = malloc(sizeof(map_pair_t));
+ p->key = key;
+ p->val = val;
+ p->next = this->list[idx];
+ this->list[idx] = p;
+ this->len++;
+}
diff --git a/lib/hashmap/hashmap.h b/lib/hashmap/hashmap.h
new file mode 100644
index 0000000..d5775c5
--- /dev/null
+++ b/lib/hashmap/hashmap.h
@@ -0,0 +1,38 @@
+/*
+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.
+*/
+
+#ifndef HASHMAP_H
+#define HASHMAP_H
+
+typedef struct pair {
+ char *key;
+ char *val;
+ struct pair *next;
+} map_pair_t;
+
+typedef struct {
+ map_pair_t **list;
+ unsigned int cap;
+ unsigned int len;
+} hashmap_t;
+
+hashmap_t *hm_new_hashmap();
+unsigned int hm_hashcode(hashmap_t *this, char *key);
+char *hm_get(hashmap_t *this, char *key);
+void hm_set(hashmap_t *this, char *key, char *val);
+
+#endif // HASHMAP_H
diff --git a/premake5.lua b/premake5.lua
index 34d98dd..1804d09 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -18,12 +18,14 @@ else
links({ "lua" })
end
-includedirs({ lua_inc_path })
+includedirs({ lua_inc_path, "lib/hashmap" })
libdirs({ lua_lib_path })
files({
"src/**.h",
"src/**.c",
+ "lib/hashmap/**.h",
+ "lib/hashmap/**.c",
})
defines({ 'LUSH_VERSION="0.0.1"' })
diff --git a/src/lua_api.c b/src/lua_api.c
index 2f967e6..21f5d39 100644
--- a/src/lua_api.c
+++ b/src/lua_api.c
@@ -325,6 +325,13 @@ static int l_set_prompt(lua_State *L) {
return 0;
}
+static int l_alias(lua_State *L) {
+ const char *alias = luaL_checkstring(L, 1);
+ const char *command = luaL_checkstring(L, 2);
+ lush_add_alias(alias, command);
+ return 0;
+}
+
// -- register Lua functions --
void lua_register_api(lua_State *L) {
@@ -361,6 +368,8 @@ void lua_register_api(lua_State *L) {
lua_setfield(L, -2, "unsetenv");
lua_pushcfunction(L, l_set_prompt);
lua_setfield(L, -2, "setPrompt");
+ lua_pushcfunction(L, l_alias);
+ lua_setfield(L, -2, "alias");
// set the table as global
lua_setglobal(L, "lush");
}
diff --git a/src/lush.c b/src/lush.c
index 83b5f08..bd8d4e8 100644
--- a/src/lush.c
+++ b/src/lush.c
@@ -16,6 +16,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "lush.h"
+#include "hashmap.h"
#include "help.h"
#include "history.h"
#include "lauxlib.h"
@@ -43,6 +44,20 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// initialize prompt format
char *prompt_format = NULL;
+// -- aliasing --
+hashmap_t *aliases = NULL;
+
+void lush_add_alias(const char *alias, const char *command) {
+ // make a new map if one doesnt exist
+ if (aliases == NULL) {
+ aliases = hm_new_hashmap();
+ }
+
+ hm_set(aliases, (char *)alias, (char *)command);
+}
+
+char *lush_get_alias(char *alias) { return hm_get(aliases, alias); }
+
// -- builtin functions --
char *builtin_strs[] = {"cd", "help", "exit", "time"};
@@ -196,7 +211,8 @@ static char *format_prompt_string(const char *input, const char *username,
// Allocate memory for the new string
char *result = (char *)malloc(new_size);
if (!result) {
- return NULL; // Handle memory allocation failure
+ perror("malloc failed");
+ return NULL;
}
// Replace placeholders in the input string and build the result string
@@ -260,6 +276,7 @@ static char *get_prompt() {
free(cwd);
return prompt;
}
+
size_t get_stripped_length(const char *str) {
size_t len = 0;
size_t i = 0;
@@ -471,6 +488,60 @@ char *lush_read_line() {
return buffer;
}
+// -- static helper for resolving aliases --
+static char *lush_resolve_aliases(char *line) {
+ // Allocate memory for the new string
+ char *result = (char *)malloc(BUFFER_SIZE);
+ if (!result) {
+ perror("malloc failed");
+ return NULL;
+ }
+
+ // Create a copy of the input line for tokenization
+ char *line_copy = strdup(line);
+ if (!line_copy) {
+ perror("strdup failed");
+ free(result);
+ return NULL;
+ }
+
+ // Start building the result string
+ char *dest = result;
+ char *arg = strtok(line_copy, " ");
+ while (arg != NULL) {
+ // Check shell aliases
+ if (aliases != NULL) {
+ char *alias = hm_get(aliases, arg);
+ if (alias != NULL) {
+ // Replace alias
+ strcpy(dest, alias);
+ dest += strlen(alias);
+ } else {
+ // No alias found, use the original token
+ strcpy(dest, arg);
+ dest += strlen(arg);
+ }
+ } else {
+ // No aliases set, just use the original token
+ strcpy(dest, arg);
+ dest += strlen(arg);
+ }
+
+ // Add a space after each token (if it's not the last one)
+ arg = strtok(NULL, " ");
+ if (arg != NULL) {
+ *dest++ = ' ';
+ }
+ }
+
+ *dest = '\0'; // Null-terminate the result string
+
+ // Clean up
+ free(line_copy);
+
+ return result;
+}
+
char **lush_split_pipes(char *line) {
char **commands = calloc(16, sizeof(char *));
if (!commands) {
@@ -685,7 +756,6 @@ int lush_run(lua_State *L, char ***commands, int num_commands) {
return ((*builtin_func[i])(L, commands));
}
}
-
return lush_execute_pipeline(commands, num_commands);
}
@@ -722,7 +792,8 @@ int main(int argc, char *argv[]) {
free(line);
continue;
}
- char **commands = lush_split_pipes(line);
+ char *expanded_line = lush_resolve_aliases(line);
+ char **commands = lush_split_pipes(expanded_line);
char ***args = lush_split_args(commands, &status);
if (status == -1) {
fprintf(stderr, "lush: Expected end of quoted string\n");
@@ -737,11 +808,13 @@ int main(int argc, char *argv[]) {
free(prompt);
free(args);
free(commands);
+ free(expanded_line);
free(line);
}
lua_close(L);
if (prompt_format != NULL)
free(prompt_format);
-
+ if (aliases != NULL)
+ free(aliases);
return 0;
}
diff --git a/src/lush.h b/src/lush.h
index ea575c7..27cf5db 100644
--- a/src/lush.h
+++ b/src/lush.h
@@ -20,6 +20,9 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#include <lua.h>
+void lush_add_alias(const char *alias, const char *command);
+char *lush_get_alias(char *alias);
+
int lush_cd(lua_State *L, char ***args);
int lush_help(lua_State *L, char ***args);
int lush_exit(lua_State *L, char ***args);