Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filters, pre_print function and max_depth #38

Merged
merged 13 commits into from
Nov 30, 2024
12 changes: 7 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ project(lsr LANGUAGES C)
set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG -fsanitize=address -Wall -Wextra -pedantic")
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")

find_package(Lua51 REQUIRED)
find_package(Lua 5.1 REQUIRED)

if (NOT LUA51_FOUND)
if (NOT LUA_FOUND)
message(FATAL_ERROR "Lua5.1 libraries not found")
else()
message(STATUS "Lua include directory: ${LUA_INCLUDE_DIR}")
Expand All @@ -26,25 +26,27 @@ file(GLOB_RECURSE SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c")

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")

set(DEFAULT_SCRIPT_PATH "$ENV{HOME}/.lsr/lsr.lua")

add_executable(lsr ${SRCS})

target_compile_definitions(lsr PRIVATE DEFAULT_SCRIPT_PATH="${CMAKE_INSTALL_PREFIX}/share/lsr/lsr.lua")
target_compile_definitions(lsr PRIVATE DEFAULT_SCRIPT_PATH="${DEFAULT_SCRIPT_PATH}")
target_include_directories(lsr PRIVATE ${LUA_INCLUDE_DIR})
target_link_libraries(lsr PRIVATE ${LUA_LIBRARIES})

add_custom_target(format COMMAND clang-format -i ${SRCS})

set(LUA_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/share/lsr")
set(LUA_INSTALL_PATH "$ENV{HOME}/.lsr")

file(GLOB LUA_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/lua/*.lua")
file(MAKE_DIRECTORY "${LUA_INSTALL_PATH}")
add_custom_command(TARGET lsr POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${LUA_INSTALL_PATH}"
COMMAND ${CMAKE_COMMAND} -E copy ${LUA_SCRIPTS} "${LUA_INSTALL_PATH}"
COMMENT "Copying Lua scripts to ${LUA_INSTALL_PATH}"
)

install(TARGETS lsr DESTINATION bin)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lua/" DESTINATION share/lsr)

if(NOT TARGET uninstall)
configure_file(
Expand Down
57 changes: 54 additions & 3 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
1. [Creating Your Own Configuration File](#creating-your-own-configuration-file)
2. [Writing Your Own Configuration](#writing-your-own-configuration)
1. [Constants](#constants)
1. [`L_colors`](#`l_colors`)
1. [`L_colors`](#l_colors)
2. [`L_recursive_max_depth`](#l_recursive_max_depth)
3. [`L_filters`](#l_filters)
2. [Functions](#functions)
1. [`L_compare_entries()`](#`l_compare_entries()`)
2. [`L_long_format()`](#`l_long_format()`)
1. [`L_compare_entries()`](#l_compare_entries())
2. [`L_long_format()`](#l_long_format())
3. [Using Defaults](#using-defaults)

Laser is highly customizable through Lua scripts. The default configuration
Expand Down Expand Up @@ -63,6 +65,40 @@ L_colors = {
DOCUMENT = "\x1b[35;3m",
}
```
#### `L_recursive_max_depth`

You can configure the maximum depth of the directory tree by modifying the
global `L_recursive_max_depth` variable. It defaults to -1 (which means
infinite). This is the default value that will be used when run `-r`. By doing
a `-rN` you can set the maximum depth to `N` and override the default value.

```lua
L_recursive_max_depth = -1
```

#### `L_filters`

You can configure the default filters by modifying the global table named
`L_filters`. You can create your own filters by adding a key with the filter name
that will be accesed by the `-f` flag. (eg. `-fmyfilter`).

The default table looks like this:

```lua
L_filters = {
recent = function(entry) return os.time() - entry.mtime < 24 * 60 * 60 end,
large = function(entry) return entry.size > 1024 * 1024 end,
small = function(entry) return entry.size < 1024 * 1024 end,
}
```

The function of the filter gets a entry table as an argument check the
definition of the entry table at the [`L_long_format`](#l_long_format)
function. Every filter must return a boolean.

> [!NOTE]
> If you add your own filters all the default filters will be overridden. You
> can still use the default filters by adding them to the `L_filters` table.

### Functions

Expand Down Expand Up @@ -143,6 +179,21 @@ function L_long_format(entry, longest_name)
end
```

#### `L_pre_print_entries()`

This function is called before the entries are printed. It can be used to add
anything before the entries are printed. The function takes no arguments, and it
should not return anything.

The default implementation is that it does nothing. But an idea to use this
could be running a command like `clear` before printing the entries.

```lua
function L_pre_print_entries()
os.execute("clear")
end
```

### Using Defaults

If you do not define these functions in your configuration file, the default
Expand Down
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ sudo cmake --install build
To uninstall you can run the following while being in the `laser` directory:

```sh
cmake --build build --target uninstall
sudo cmake --build build --target uninstall
```

> [!NOTE]
> This dosen't install the shell completions for the cli but you can add them
> by placing the files from the `completions` directory in a directory that is in
> your `$PATH`. Or source the file from your `bashrc`, `zshrc` or `config.fish`
> file.
> [!NOTE]
> This dosen't install the shell completions for the cli but you can add them
> by placing the files from the `completions` directory in a directory that is
> in your `$PATH`. Or source the file from your `bashrc`, `zshrc` or
> `config.fish` file.

## Usage

Expand All @@ -81,11 +81,12 @@ lsr some-directory

If you'd like to configure the program's behavior, or change the default colors,
add icons and more. You can configure the program with lua :fire:. A default
configuration will be installed at `/usr/local/share/lsr/`. But if you want to
configuration will be installed at `$HOME/.lsr/`. But if you want to
write some own configuration you can place it in `~/.config/lsr/lsr.lua`.

Copy the files from `/usr/local/share/lsr/` to `~/.config/lsr/` and you can edit
them now.
Copy the files from `$HOME/.lsr` to `~/.config/lsr/` and you can edit them (do
not change in the files in the `$HOME/.lsr` directory because they will be used
as default if there are missing values in the `.config`).

Check out the [configuration guide](/CONFIGURATION.md)

Expand All @@ -99,13 +100,16 @@ you can directly pass in the flags.
- `-D` or `--Directories` shows only directories
- `-F` or `--Files` shows only files
- `-S` or `--Symlinks` shows only symlinks
- `-G` or `--Git` shows only the entries that are not named in `.gitignore` (works only if there exists a `.gitignore`)
- `-G` or `--Git` shows only the entries that are not named in `.gitignore`
(works only if there exists a `.gitignore`)
- `-r` or `--recursive` shows directory tree structure
- `-r` or `--recursive` has an optional value for max depth and it can be
used by using `-r2` or `--recursive=2` by default the depth is until last
level
- `-l` or `--long` displays in long format (permissions, last modified, size and owner)

- `-r` or `--recursive` has an optional value for max depth and it can be
used by using `-r2` or `--recursive=2` by default the depth is until last
level
- `-l` or `--long` displays in long format (permissions, last modified, size
and owner)
- `-fmyfilter` or `--filter=myfilter` applies a user defined filter from lua
check the [CONFIGURATION.md](/CONFIGURATION.md)

The flags can be chained for example using:
```sh
Expand Down
22 changes: 21 additions & 1 deletion include/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,30 @@
#include "utils.h"
#include <stdio.h>

#define LASER_VERSION "1.0.3"
#define LASER_VERSION "1.1.0"

typedef struct laser_opts
{
int show_all;
int show_files;
int show_directories;
int show_symlinks;
int show_git;
int show_tree;
int show_long;
int recursive_depth;

int filter_count;
const char **filters;

const char *dir;
const char *parentDir;
} laser_opts;

laser_opts laser_cli_parsecmd(int argc, char **argv);
void laser_cli_generate_completions(const char *shell);
void laser_cli_print_help(void);

void laser_cli_destroy_opts(laser_opts opts);

#endif
9 changes: 9 additions & 0 deletions include/init_lua.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,13 @@ lua_State *laser_init_lua(void);
void laser_lua_load_script(const char *script_path);
void laser_lua_set_package_path(const char *script_path);

#define laser_lua_CALL_NOARGS_NORET(func_name) \
lua_getglobal(L, func_name); \
if (lua_pcall(L, 0, 0, 0) != LUA_OK) \
{ \
fprintf(stderr, "lsr: error in %s: %s\n", func_name, \
lua_tostring(L, -1)); \
lua_pop(L, 1); \
}

#endif
1 change: 1 addition & 0 deletions include/laser.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef LASER_LASER_H
#define LASER_LASER_H

#include "cli.h"
#include "colors.h"
#include "sort.h"
#include "utils.h"
Expand Down
9 changes: 9 additions & 0 deletions include/lua_filters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef LASER_LUA_FILTERS_H
#define LASER_LUA_FILTERS_H

#include "init_lua.h"
#include "laser.h"

int lua_filters_apply(laser_opts opts, struct laser_dirent *entry);

#endif
15 changes: 0 additions & 15 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,6 @@
#include <time.h>
#include <unistd.h>

typedef struct laser_opts
{
int show_all;
int show_files;
int show_directories;
int show_symlinks;
int show_git;
int show_tree;
int show_long;
int recursive_depth;

const char *dir;
const char *parentDir;
} laser_opts;

char **laser_utils_grow_strarray(char **array, size_t *alloc_size,
size_t count);
int laser_string_in_sorted_array(char *target, char **array, int size);
Expand Down
5 changes: 5 additions & 0 deletions lua/filters.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
L_filters = {
recent = function(entry) return os.time() - entry.mtime < 24 * 60 * 60 end,
large = function(entry) return entry.size > 1024 * 1024 end,
small = function(entry) return entry.size < 1024 * 1024 end,
}
4 changes: 3 additions & 1 deletion lua/lsr.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require "colors"
require "filters"
local utils = require "utils"

L_recursive_max_depth = -1

function L_compare_entries(entry1, entry2, entry1_is_dir, entry2_is_dir)
if entry1_is_dir and not entry2_is_dir then return -1 end
if not entry1_is_dir and entry2_is_dir then return 1 end
Expand All @@ -23,5 +26,4 @@ function L_long_format(entry, longest_name)
end

function L_pre_print_entries()
print("this is default pre_print")
end
44 changes: 39 additions & 5 deletions src/cli.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "cli.h"
#include "init_lua.h"

static const struct option long_args[] = {
{"all", 0, 0, 'a'},
Expand All @@ -8,6 +9,7 @@ static const struct option long_args[] = {
{"Git", 0, 0, 'G'},
{"long", 0, 0, 'l'},
{"recursive", optional_argument, 0, 'r'},
{"filter", required_argument, 0, 'f'},
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"completions", required_argument, 0, 0},
Expand All @@ -22,6 +24,7 @@ static const char *descriptions[] = {
"Show entries that are not defined in .gitignore",
"Use long format",
"Show in tree format",
"Filter out files using lua filters (`L_filters` in lsr.lua)",
"Print the current version",
"Print help message",
"Generate shell completions",
Expand All @@ -39,9 +42,18 @@ laser_opts laser_cli_parsecmd(int argc, char **argv)
int show_long = 0;
const char *dir = ".";

// set default recursive_depth from lua
lua_getglobal(L, "L_recursive_max_depth");
if (lua_isnumber(L, -1))
recursive_depth = (int)lua_tointeger(L, -1);
lua_pop(L, 1);

int filter_count = 0;
const char **filters = NULL;

int opt;

while ((opt = getopt_long(argc, argv, "aFDSGr::lvh", long_args, NULL)) !=
while ((opt = getopt_long(argc, argv, "aFDSGr::lvhf::", long_args, NULL)) !=
-1)
{
switch (opt)
Expand Down Expand Up @@ -90,6 +102,21 @@ laser_opts laser_cli_parsecmd(int argc, char **argv)
case 'h':
laser_cli_print_help();
exit(0);
case 'f':
if (optarg == NULL)
{
fprintf(stderr,
"lsr: couldn't filter files, filter not passed or "
"not formatted correctly\nlsr: filter usage "
"`-fmyfilter` or `--filter=myfilter\n");
exit(1);
}

filters = realloc(filters, sizeof(char *) * (filter_count + 1));
filters[filter_count] = strdup(optarg);
filter_count++;

break;
case 0:
if (strcmp(long_args[optind - 1].name, "completions") == 0)
{
Expand All @@ -105,10 +132,10 @@ laser_opts laser_cli_parsecmd(int argc, char **argv)
if (optind < argc)
dir = argv[optind];

return (laser_opts){show_all, show_files, show_directories,
show_symlinks, show_git, show_tree,
show_long, recursive_depth, dir,
.parentDir = dir};
return (laser_opts){
show_all, show_files, show_directories, show_symlinks, show_git,
show_tree, show_long, recursive_depth, filter_count, filters,
dir, .parentDir = dir};
}

void laser_cli_generate_completions(const char *shell)
Expand Down Expand Up @@ -203,3 +230,10 @@ void laser_cli_print_help(void)
printf(" --%-28s %s\n", long_args[i].name, descriptions[i]);
}
}

void laser_cli_destroy_opts(laser_opts opts)
{
for (int i = 0; i < opts.filter_count; i++)
free((void *)opts.filters[i]);
free(opts.filters);
}
1 change: 1 addition & 0 deletions src/init_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ void laser_lua_set_package_path(const char *script_path)
lua_pop(L, 1);
}
}

Loading
Loading