FM - A C89 compatible file manager

started by alice 2026-06-26

FM - The c89 compatible file manager.

I recently got an idea. Wouldn't it be fun to try to write a file manager in C without using while, for, do or any other traditional loop or user defined function, with it all being one file with one massive main function?
goto is a feature I had yet to explore, that's when i decided to learn goto by writing a simple file manager.
How would the control flow be? How far can I get with using just if?

As I wondered I just started on it after asking what Deci thought of the project. He called it insane and that ideas like that only worsened the effect of anti-depression medicines, and so i had the approval I needed to jump into it.

It started by just doing simple file management one by one in a .c file.
After I had looked some at how to create files, directories, remove them and some more I wanted to have it as a TUI, as all good things has a proper and nice looking UI.

With using ansi escape sequences I would clear the screen and move the cursor as well as doing colouring and more with the text, but as a start I will only be clearing and cleaning the screen without using termios as that can be annoying in the case of an improper exit.
printf is my tool of choice for making the TUI, with sscanf being for user input.

At first I added just two commands to the file manager. Creating a directory and changing the current directory. I quickly saw the need to print what is in the current directory and so I simply added a loop for listing it, with a printf statement that says which commands are available. With some simple alignment and formatting it looked quite good. I added a label for if it is a file or directory, and will later do separate colouring for it as well.

As I added more features I quickly wanted a faster way to match names without writing the whole name, and globing came to mind. Not as complex as regex, which might sound bad but it also means it is a lot simpler than regex.
Coincidentally tsodings video on glob.h came up, and I thought, why not just use that?, but that idea quickly faded as I saw the C++ style comments, which is not C89 compatible and i just dislike them in general.

This does not mean that it was useless, as I wrote myglob.h as I watched the stream where he wrote glob.h.

Mine would not be anything special, and just work on ASCII strings, but that was all I needed. Combined it totalled 120 lines of code, before I added documentation comments as well as the helped function myglob which accepts two strings.
The first being the pattern and the second being the string to match against.
Example usage:

c
char* str = "Some Message.";
myglob ("[A-Z][!A-Z]*.", str);

This simply checks if the string does start with a capital letter lead by a non capital letter and ends with a dot.

For a proper explanation I wrote a comment in the header file itself.

c
/**

 * @brief This is how you use myglob.h

 *

 * To get just the text if matched and error if unmatched,

 * use `myglob`. It takes two arguments,

 * The pattern to look for and the string to check.

 * If the pattern matches with the input text it will return the match.

 * If it does not match it returns the string `"ERROR"`.

 *

 * EXAMPLE:

 * myglob ("[abc][a-f]*STR", "acANYTEXTATALL_STR"); This will return the string

`"acANYTEXTATALL_STR"` as it matches this expression.

 * myglob ("[abc]!*STR", "acANYTEXTATALL_STR");     This will return `"ERROR"`

as it does not match, because i put a `!` in the pattern.

 *

 * Patters:

 * '?',      - matches any one char.

 * '*',      - matches anything.

 * '[abc]',  - matches with one of the chars in the brackets.

 * '[!abc]', - does not match any of the chars in the bracket but everything

else insted.

 * '[a-z]',  - matches one char in the range given, works for numbers too.

 * '\\'      - matches literal backslash.

 *

 * You can also use `myinternalglob` to just get if it matched,

 * If it is unmatched or if it has an syntax error (invalid pattern).

 * `0` is valid, `-1` is invalid, `-2` is syntax error.

 *

 * EXAMPLE:

 * if (myinternalglob(pattern, text) == MYGLOB_MATCHED) return text;

 * else return "ERROR";

 */

And if one goes to the helper function which is myglob this comment explains the usage in a simpler fashion.

c
/**

 * @brief User glob function for simple pattern matches on ascii strings.

 *

 * Matches patterns on strings: '?', '*', '[abc]', '[!abc]', '[a-z]', '\\'.

 *

 * EXAMPLE:

 * myglob ("[abc]*",  "a string"); -> "a string" | as it begins with `a` from the pattern and a wildcard for matching anything.

 * myglob ("[!abc]*", "a string"); -> "ERROR"    | as the pattern looks for all but [abc] but it begins with an `a`.

 *

 * @param pattern to match with.

 * @param text to match the pattern on.

 * @return Pointer to the matched text on success, or the literal string "ERROR".

 */

To see tests for a lot of cases check out myglob_tests.c.

And now, I have a simple TUI start and an easier way to match names.
For most commands you may now use the globing from myglob.h as well as to filter the main listing of the current directory content.
An example could be that I just want c and h files listed.
For this I would do f *.[ch], as f is the prefix for filter.

Now i will end this off with a simple example from the file manager.

c:cd t:touch d:mkdir p:cp r:rm f:filter e:edit q:exit
=====================================================
DIR| /home/alice/git/mine/misc/c/goto [F: *.[ch]]
  F|  CBS.c
  F|  cbs.h
  F|  file_util_commands.c
  F|  filemanager.c
  F|  glob_tests.c
  F|  grid.c
  F|  myglob.h
   |> p CBS.c C_Build_System.c

ok i’m too early in C to follow the glob stuff but i get the gist, you banned yourself from loops and functions and built a file manager out of pure goto for fun? that’s so cursed, i love it

Globing is also in the shell, forgot if it is readline or bash that adds it. If you have a directory named dir and do ls di?<TAB> it should correct it do ls dir as ? matches with any char.


Now with colours!

Log in or register to reply.