VargonMUD work continues. Here is a brief summary of the work done so far:
varargs string color_wrap(string str, int width, int indent, object player);
Note: Supports slightly-annoying pseudo-color 'RAINBOW'
Kriton should be immortalized!
Male elf of the Adventurers Level: 20
In real life: Kristian Spouse: (unmarried)
Birthday: Sun Feb 16 22:15:35 1997 Position: Administrator
Homepage: https://kristianoye.wordpress.com/
LinkedIn: https://www.linkedin.com/in/kristianoye
Facebook: https://facebook.com/kristianoye
Twitter / X: https://x.com/kristianoyeSponsor: None
Email: kriton@gameworkshop.com
Age: 12 days 3 hours 11 minutes 58 seconds.
Time on this session: 35 minutes 9 seconds.
Host machine: localhost
Kriton has no unread mail.
No plan.
Guesta
Male elf of the Adventurers Level: 1
In real life: Kris Spouse: (unmarried)
Birthday: Sat Feb 21 17:01:48 2026 Position: Player
Homepage: (None)
Sponsor: None
Email: kriton@gameworkshop.com
Age: 25 minutes 38 seconds.
Time on this session: 12 minutes 51 seconds.
Host machine: localhost
Guesta has no unread mail.
No plan.
This API allows objects to watch files and directories for changes, creations, and deletions. It supports both internal changes (made through the driver) and external changes (made outside the driver, e.g. through a text editor).
Example:
// Testbed for stuff
// -Kriton 2026-02-22
#include <dbc.h>
#include <filewatch.h>
void create() {
watch_file(__DIR__, function(class FileWatcherEvent e) {
message("write", sprintf("%s was modified: %O", e.file, e), find_player("kriton"));
}, WATCH_ALL);
}
kriton@vargonmud:~> rm foo
/u/k/kriton was modified: CLASS( 8 elements
"/u/k/kriton",
"/u/k/kriton/foo",
528,
1,
0,
/std/user#2 ("Kriton should be immortalized!"),
({ /* sizeof() == 4 */
/adm/obj/simul_efun,
/std/user#2 ("Kriton should be immortalized!"),
/bin/system/_rm,
/std/user#2 ("Kriton should be immortalized!")
}),
/std/user#2 ("Kriton should be immortalized!")
)
/u/k/kriton was modified: CLASS( 8 elements
"/u/k/kriton",
"/u/k/kriton/foo",
17,
1,
0,
/bin/system/_rm,
({ /* sizeof() == 3 */
/adm/obj/simul_efun,
/bin/system/_rm,
/std/user#2 ("Kriton should be immortalized!")
}),
/std/user#2 ("Kriton should be immortalized!")
)
/u/k/kriton/foo: Ok.
Here is the man page for the watch_file() function:
NAME
watch_file() - Watch a filesystem object for changes.
SYNOPSIS
varargs int watch_file(string file, function callback, int eventTypeId);
DESCRIPTION
Watch the specified file or directory for changes. Whenever a change is
detected, the callback function will be called with a single argument,
a FileWatcherEvent object describing the change. The eventTypeId
argument can be used to specify which types of events to watch for;
if it is not provided, it defaults to FILE_MODIFIED.
The eventTypeId argument is an integer bitfield that can be constructed by
ORing together the following flags:
FILE_DELETED - Watch for file deletions.
FILE_MODIFIED - Watch for file modifications.
FILE_CREATED - Watch for file creations.
FILE_RENAMED - Watch for file renames.
FILE_READ - Watch for file reads (note: this only applies to reads
made within the mudlib runtime, not external reads).
FILE_ALL - Watch for all file events (created, deleted, modified, renamed, read).
DIR_ENTRY_CHANGE - Watch for changes to directory entries
(e.g. files being added or removed from a directory).
DIR_CREATED - Watch for directory creations.
DIR_DELETED - Watch for directory deletions.
DIR_RENAMED - Watch for directory renames.
DIR_ALL - Watch for all directory events (created, deleted, renamed).
WATCH_ALL is a convenient alias for FILE_ALL | DIR_ALL.
The callback function should have the following signature:
void callback(class FileWatcherEvent event)
where FileWatcherEvent is a class with the following fields:
string file - The file that was changed.
string eventFile - The file that triggered the event (e.g. the new
name of a renamed file).
int eventTypeId - An integer bitfield indicating the type(s) of
event that occurred (e.g. FILE_MODIFIED, FILE_DELETED).
mixed success - Whether the operation was successful. For example,
for a FILE_MODIFIED event, this would indicate whether the file
was successfully modified.
string previousName - For rename events, the previous name of the file.
object previousObject - The object that initiated the change.
object thisPlayer - The player associated with the change.
This function returns a watch ID that can be used to unwatch the file
later with unwatch_file().
SEE ALSO
unwatch_file()
AUTHOR
Kriton@VargonMUD, 2026-02-22
kriton@vargonmud:/bin/soul> scan
Scanning:
(no name) [OBJ(/u/k/kriton/workroom)] [uid:Kriton] [euid:Kriton]
1: Kriton should be immortalized! [OBJ(/adm/save/users/k/kriton)] [UID:Kriton] [EUID:Kriton]
kriton@vargonmud:/bin/soul>
kriton@vargonmud:/adm> eval return query_privs(this_player())
Result = "kriton:SUPERUSER:DBUSER"
private void create() {
set_name("ls - list directory contents");
set_usage("ls [OPTION]... [FILE]...");
set_description("List information about the FILEs (the current directory by default)."
" Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.");
set_author("Kristian Oye <kriton@VargonMUD>");
set_version("0.9");
set_flags_var("flags");
set_keywords("list", "files", "directory");
set_category( HELP_CMDS_SYSTEM );
set_help_file("_lsx.md");
set_defaults(function(object cmd) {
cmd->set_format( LSX_FMT_ACROSS );
cmd->set_sort( LSX_SORT_NAME );
cmd->set_sort_dir( LSX_SORT_ASC );
});
add_flag("-1", "List one file per line", (: set_format(LSX_FMT_SINGLECOL) :));
add_flag("-a|--all", "View hidden files", LSX_VIEW_HIDDEN);
add_flag("-A|--almost-all", "View hidden files except . and ..", LSX_VIEW_ALMOST);
add_flag("-B|--ignore-backups", "Do not list implied backup files", LSX_NO_BACKUPS);
add_flag("--color,COLOR_WHEN?=*always,auto,never", "Colorize the output", LSX_VIEW_COLOR);
add_flag("-C", "List entries by columns", (: set_format(LSX_FMT_ACROSS) :));
add_flag("--full-time", "List complete time information for files", LSX_FULL_TIME);
add_flag("-F|--classify", "Append indicator (one of */=>@|) to entries", LSX_CLASSIFY);
add_flag("-l", "Use a long listing format", (: set_format(LSX_FMT_VERBOSE) :));
add_flag("-m", "Fill width with a comma separated list of entries", (: set_format(LSX_FMT_COMMAS) :));
add_flag("-Q|--quote-names", "Enclose entry names in double quotes", LSX_QUOTE_NAMES);
add_flag("-s|--size", "Print the allocated size of each file", LSX_SHOW_SIZE);
add_flag("-r|--reverse", "Reverse the order of the sort", (: set_sort_dir(LSX_SORT_DESC) :));
add_flag("-R|--recursive", "List subdirectories recursively", LSX_RECURSIVE);
add_flag("--sort,WORD==size,time,extension,width", "Sort entries by WORD instead of name: size - by file size; time - by modification time; extension - by file extension; width - by terminal width", (: set_sort(LSX_SORT_SIZE) :));
add_flag("-S", "Sort by file size, largest first.", (: set_sort(LSX_SORT_SIZE) :));
add_flag("-x", "List entries by lines instead of by columns", (: set_format(LSX_FMT_HORZONTAL) :));
set_see_also("dir");
build_help();
}
...
int cmd_ls(string str) {
if (!parse_cmd(ref str))
return notify_fail(query_error());
... do stuff ...
}
The build_help() function generates nicely formatted help text based on the flags and their descriptions, so
the command author doesn't have to worry about formatting the help text manually.
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
-1
List one file per line
-a, --all
View hidden files
-A, --almost-all
View hidden files except . and ..
-B, --ignore-backups
Do not list implied backup files
--color COLOR_WHEN
Colorize the output
-C
List entries by columns
--full-time
List complete time information for files
-F, --classify
Append indicator (one of */=>@|) to entries
-l
Use a long listing format
-m
Fill width with a comma separated list of entries
-Q, --quote-names
Enclose entry names in double quotes
-s, --size
Print the allocated size of each file
-r, --reverse
Reverse the order of the sort
-R, --recursive
List subdirectories recursively
--sort WORD
Sort entries by WORD instead of name: size - by file size; time - by modification time; extension - by file extension; width - by terminal width
-S
Sort by file size, largest first.
-x
List entries by lines instead of by columns
SEE ALSO
dir
AUTHOR
Kristian Oye
Previous behavior:
eval return strlen(" ")
Result = 1
New behavior:
eval return strlen(" ")
Result = 6
kriton@vargonmud:~/bin> eval return glob_dir("/std/**/*.c")
Result = [
"/std/ObItems.c",
"/std/Object.c",
"/std/abs.c",
"/std/add_money.c",
"/std/addclone.c",
"/std/advance_room.c",
"/std/ansi.c",
"/std/armour.c",
"/std/bag_logic.c",
"/std/barkeep.c",
"/std/bboard.c",
"/std/castle.c",
"/std/command.c",
"/std/container.c",
"/std/container2.c",
"/std/daemon.c",
"/std/drink.c",
"/std/emote.c",
"/std/find_sponsor.c",
"/std/food.c",
"/std/guild_object.c",
"/std/idle.c",
"/std/item.c",
"/std/jdebug.c",
"/std/join_room.c",
"/std/living.c",
"/std/money.c",
"/std/monster.c",
"/std/moom.c",
"/std/moom.new.c",
"/std/move.c",
"/std/null.c",
"/std/pier.c",
"/std/poison.c",
"/std/potion.c",
"/std/potion_empty.c",
"/std/potion_tracker.c",
"/std/prop_logic.c",
"/std/quest_ob.c",
"/std/room.c",
"/std/shop.c",
"/std/shroud.c",
"/std/sign.c",
"/std/train.c",
"/std/vault.c",
"/std/vendor.c",
"/std/weapon.c",
"/std/wiz_echo.c",
"/std/adt/cstack.c",
"/std/adt/ilist.c",
"/std/adt/iqueue.c",
"/std/adt/iset.c",
"/std/adt/istack.c",
"/std/adt/queue.c",
"/std/adt/semaphore.c",
"/std/adt/stack.c",
"/std/esoul/shared.c",
"/std/etc/debug.c",
"/std/etc/heading.c",
"/std/etc/lockable.c",
"/std/etc/move.new.c",
"/std/etc/name_server.c",
"/std/etc/pad.c",
"/std/etc/str_more.c",
"/std/fun/check_string.c",
"/std/fun/delete.c",
"/std/fun/find_match.c",
"/std/fun/get_text.c",
"/std/fun/wiz_present.c",
"/std/hm/castle.c",
"/std/hm/hm_room.c",
"/std/hm/room_maker.c",
"/std/item/identifiers.c",
"/std/living/body.c",
"/std/living/combat.c",
"/std/living/env.c",
"/std/living/follow.c",
"/std/living/gender.c",
"/std/living/messages.c",
"/std/living/skills.c",
"/std/obj/body_part.c",
"/std/obj/brand.c",
"/std/obj/corpse.c",
"/std/obj/marker.c",
"/std/obj/not_deed.c",
"/std/obj/player_list.c",
"/std/obj/telnet.c",
"/std/obj/torch.c",
"/std/obj/wed_ring.c",
"/std/obj/wed_ring2.c",
"/std/obj/workroom.c",
"/std/obj/ring/_orgasm.c",
"/std/obj/ring/_ring.c",
"/std/obj/working/wed_ring.c",
"/std/room/exits.c",
"/std/room/items.c",
"/std/room/senses.c",
"/std/virtual/_daemon.c",
"/std/virtual/_server.c",
"/std/virtual/compile.c"
]
kriton@vargonmud:~> eval return reduce_array( ({ 1,2,3 }), (: $1 + $2 :))
Result = 6
varargs string format_table(string *items, int direction, int width, int space_between)
Note: If width is not specified, it will use the player or previous object's terminal
width with a fallback of 80 characters. Also, this function is color-agnostic. Any
color codes are ignored when calculating column widths, but are preserved in the output.
if (arrayp(files)) {
string txt = format_table( map(files, (: $1[0] :)), 1, term_width );
results += explode(txt, "\n");
}
ls /std
ObItems.c ansi.c container.c find_sponsor.c item monster.c pier.c room vendor.c
Object.c armour.c container2.c food.c item.c moom.c poison.c room.c virtual
abs.c bag_logic.c daemon.c foode.c.feh jdebug.c moom.new.c potion.c shop.c weapon.c
add_money.c barkeep.c drink.c fun join_room.c move.c potion_empty.c shroud.c wiz_echo.c
addclone.c bboard.c emote.c guild_object.c living null.c potion_tracker.c sign.c
adt castle.c esoul hm living.c obj prop_logic.c train.c
advance_room.c command.c etc idle.c money.c old quest_ob.c vault.c
if (!parse_cmd(ref str))
return notify_exit();