diff --git a/.cursorindexingignore b/.cursorindexingignore new file mode 100644 index 00000000..953908e7 --- /dev/null +++ b/.cursorindexingignore @@ -0,0 +1,3 @@ + +# Don't index SpecStory auto-save files, but allow explicit context inclusion via @ references +.specstory/** diff --git a/.specstory/.gitignore b/.specstory/.gitignore new file mode 100644 index 00000000..c5b4129e --- /dev/null +++ b/.specstory/.gitignore @@ -0,0 +1,4 @@ +# SpecStory project identity file +/.project.json +# SpecStory explanation file +/.what-is-this.md diff --git a/src/fe-common/core/fe-expandos.c b/src/fe-common/core/fe-expandos.c index 6fba4071..93069d10 100644 --- a/src/fe-common/core/fe-expandos.c +++ b/src/fe-common/core/fe-expandos.c @@ -21,6 +21,12 @@ #include "module.h" #include #include +#include + +/* Nick column context variables */ +static char *current_nick = NULL; +static char *current_mode = NULL; +static gboolean nick_context_valid = FALSE; /* Window ref# */ static char *expando_winref(SERVER_REC *server, void *item, int *free_ret) @@ -41,6 +47,80 @@ static char *expando_winname(SERVER_REC *server, void *item, int *free_ret) return active_win->name; } +/* Nick column aligned - returns padded string with mode and nick */ +static char *expando_nickaligned(SERVER_REC *server, void *item, int *free_ret) +{ + int width, mode_len, nick_len, available_for_nick; + const char *mode; + char *result; + + if (!settings_get_bool("nick_column_enabled") || !nick_context_valid || !current_nick) { + return ""; + } + + width = settings_get_int("nick_column_width"); + mode = current_mode ? current_mode : ""; + mode_len = strlen(mode); + nick_len = strlen(current_nick); + + /* Always reserve 1 space for mode (even if empty) */ + available_for_nick = width - 1; + + if (mode_len == 0) { + /* No mode - use space + nick */ + if (nick_len <= available_for_nick) { + /* Nick fits - pad from left */ + int padding = width - 1 - nick_len; /* -1 for space */ + result = g_strdup_printf("%*s %s", padding, "", current_nick); + } else { + /* Nick too long - truncate with >> */ + result = g_strdup_printf(" %.*s>>", available_for_nick - 2, current_nick); + } + } else { + /* Has mode */ + int total_len = mode_len + nick_len; + if (total_len <= width) { + /* Mode + nick fits - pad from left */ + int padding = width - total_len; + result = g_strdup_printf("%*s%s%s", padding, "", mode, current_nick); + } else { + /* Too long - truncate nick with >> */ + int available_for_nick_with_mode = width - mode_len - 2; /* -2 for >> */ + if (available_for_nick_with_mode > 0) { + result = g_strdup_printf("%s%.*s>>", mode, available_for_nick_with_mode, current_nick); + } else { + /* Mode itself too long */ + result = g_strdup_printf("%.*s>>", width - 2, mode); + } + } + } + + /* Debug output */ + if (settings_get_bool("debug_nick_column")) { + printf("DEBUG nickaligned: nick='%s', mode='%s', width=%d, result='%s'\n", + current_nick, mode, width, result); + } + + *free_ret = TRUE; + return result; +} + +/* Update nick context for expandos */ +void update_nick_context(const char *nick, const char *mode) +{ + g_free(current_nick); + g_free(current_mode); + current_nick = g_strdup(nick); + current_mode = g_strdup(mode ? mode : ""); + nick_context_valid = TRUE; +} + +/* Clear nick context */ +void clear_nick_context(void) +{ + nick_context_valid = FALSE; +} + void fe_expandos_init(void) { expando_create("winref", expando_winref, @@ -49,10 +129,14 @@ void fe_expandos_init(void) expando_create("winname", expando_winname, "window changed", EXPANDO_ARG_NONE, "window name changed", EXPANDO_ARG_WINDOW, NULL); + expando_create("nickaligned", expando_nickaligned, + "message public", EXPANDO_ARG_NONE, + "message own_public", EXPANDO_ARG_NONE, NULL); } void fe_expandos_deinit(void) { expando_destroy("winref", expando_winref); expando_destroy("winname", expando_winname); + expando_destroy("nickaligned", expando_nickaligned); } diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 980da809..95de3bcd 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -37,6 +37,10 @@ #include #include +/* Forward declarations for nick column functions */ +void update_nick_context(const char *nick, const char *mode); +void clear_nick_context(void); + #define ishighalnum(c) ((unsigned char) (c) >= 128 || i_isalnum(c)) #define isnickchar(a) \ (i_isalnum(a) || (a) == '`' || (a) == '-' || (a) == '_' || \ @@ -218,6 +222,11 @@ static void sig_message_public(SERVER_REC *server, const char *msg, if (printnick == NULL) printnick = nick; + /* Update nick context for expandos */ + if (settings_get_bool("nick_column_enabled")) { + update_nick_context(printnick, nickmode); + } + format_create_dest(&dest, server, target, level, NULL); dest.address = address; dest.nick = nick; @@ -292,6 +301,11 @@ static void sig_message_own_public(SERVER_REC *server, const char *msg, nickmode = channel_get_nickmode(channel, server->nick); + /* Update nick context for expandos */ + if (settings_get_bool("nick_column_enabled")) { + update_nick_context(server->nick, nickmode); + } + window = channel == NULL ? NULL : window_item_window((WI_ITEM_REC *) channel); @@ -802,6 +816,11 @@ void fe_messages_init(void) settings_add_bool("lookandfeel", "show_extended_join", FALSE); settings_add_bool("lookandfeel", "show_account_notify", FALSE); + /* Nick column feature settings */ + settings_add_bool("lookandfeel", "nick_column_enabled", FALSE); + settings_add_int("lookandfeel", "nick_column_width", 12); + settings_add_bool("lookandfeel", "debug_nick_column", FALSE); + signal_add_last("message public", (SIGNAL_FUNC) sig_message_public); signal_add_last("message private", (SIGNAL_FUNC) sig_message_private); signal_add_last("message own_public", (SIGNAL_FUNC) sig_message_own_public); diff --git a/src/fe-common/core/fe-messages.h b/src/fe-common/core/fe-messages.h index 03f7da7b..4480a8d8 100644 --- a/src/fe-common/core/fe-messages.h +++ b/src/fe-common/core/fe-messages.h @@ -9,4 +9,8 @@ char *channel_get_nickmode(CHANNEL_REC *channel, const char *nick); extern GHashTable *printnicks; +/* Nick column context functions */ +void update_nick_context(const char *nick, const char *mode); +void clear_nick_context(void); + #endif diff --git a/themes/default.theme b/themes/default.theme index a44cfc81..6c079b63 100644 --- a/themes/default.theme +++ b/themes/default.theme @@ -115,8 +115,11 @@ abstracts = { ## messages ## - # the basic styling of how to print message, $0 = nick mode, $1 = nick - msgnick = "%K<%n$0$1-%K>%n %|"; + # the basic styling of how to print message + # NICK COLUMN FEATURE: when enabled, uses $nickaligned expando + # Enable with: /SET nick_column_enabled ON + # Configure width: /SET nick_column_width 12 + msgnick = "%K<%n$nickaligned%K>%n %|"; # message from you is printed. "msgownnick" specifies the styling of the # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the