I've recently put together a few new features and updates
 for GNU Screen, in a (transient?) fork called tscreen[0].  This
 is primarily because I've always had the belief that GNU Screen
 was not being actively developed - but also because there are
 things that I personally would like to see added, changed, or
 dropped.

  One of the most interesting new features is the ability to
 define aliases.  In my current implementation there are two
 kinds of aliases:

    1.  Mere synonyms.
    2.  Constant calls to other functions with a list of arguments.

  As an example the following makes "shout" an alias for "echo":

  alias shout echo

  A more interesting alias is one with some actual activity behind
 it.  This is a typical example in four parts:

#
#  1. Caption toggle
#
alias caption_off  eval "caption splitonly"
alias caption_on   eval "caption always"

#
#  2. Statusbar toggle
#
alias status_off   eval "hardstatus ignore"
alias status_on    eval "hardstatus alwayslastline"


#
#  3. Disable both caption and status, and show a message.
#
alias fullscreen   eval "status_off" "caption_off" "echo 'fullscreen - \"Ctrl-a 
F\" to return'"
alias captioned    eval "status_on"  "caption_on"  "echo 'fullscreen - \"Ctrl-a 
f\" for fullscreen'"


#
#  4. Bind the keys
#
bind f eval fullscreen
bind F eval captioned


  In terms of implementation the code is pretty straightforward, and
 some of the actual details show through.  We maintain a global linked
 list of aliases.

  The structure is :

/*
 * Command aliases.
 */
struct alias {
  /* next in our linked list */
  struct alias *next;
  char *alias_name;
  char *alias_value;
  int  alias_arg_count;
  char **alias_args;
};

  For the simple case we have an entry of the form:
    
    alias{
    alias_name => "shout",
    alias_value => "echo",
    }

  For a more complex case we'd have this:

    alias{
    alias_name => "fullscreen"
    alias_value => "eval",
    alias_args => [ "status_off", "caption_off", "echo 'blah'" ],
    alias_args_count => 3
  }

  As you can see this alias is in two parts:

    1.  It defines "fullscreen" as actually invoking "eval".
    2.  When fullscreen is called it will invoke eval with the
       list of three arguments we've been passed at create time.

  Anyway, Juergen Weigert, suggested I drop the list a mail with
 a couple of comments.  I hope this serves as a suitable introduction,
 and the patch is attached - against the current git tree.

Steve
-- 
Managed Anti-Spam Service
http://mail-scanning.com/


 0 - http://www.steve.org.uk/Software/tscreen/


diff --git a/src/comm.c b/src/comm.c
index 27f67c7..29cecb9 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -51,6 +51,7 @@ struct comm comms[RC_LAST + 1] =
 #ifdef MULTIUSER
   { "addacl",		ARGS_1234 },
 #endif
+  { "alias",            ARGS_12|ARGS_ORMORE },
   { "allpartial",	NEED_DISPLAY|ARGS_1 },
   { "altscreen",	ARGS_01 },
   { "at",		NEED_DISPLAY|ARGS_2|ARGS_ORMORE },
diff --git a/src/extern.h b/src/extern.h
index 3e64b7f..bfb4ee1 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -178,6 +178,10 @@ extern int   OpenPTY __P((char **));
 extern void  InitPTY __P((int));
 
 /* process.c */
+extern void  AddAlias( const char *name, const char *val , char **args, int count);
+struct alias * FindAlias( char *name );
+extern void  DelAlias( const char *name  );
+
 extern void  InitKeytab __P((void));
 extern void  ProcessInput __P((char *, int));
 #ifdef MAPKEYS
diff --git a/src/process.c b/src/process.c
index 79cb716..e231574 100644
--- a/src/process.c
+++ b/src/process.c
@@ -224,6 +224,20 @@ static int maptimeout = 300;
 #endif
 
 
+/*
+ * Command aliases.
+ */
+struct alias {
+  /* next in our linked list */
+  struct alias *next;
+  char *alias_name;
+  char *alias_value;
+  int  alias_arg_count;
+  char **alias_args;
+};
+struct alias *g_aliases_list = NULL;
+
+
 /* digraph table taken from old vim and rfc1345 */
 static const unsigned char digraphs[][3] = {
     {' ', ' ', 160},	/* ? */
@@ -2516,6 +2530,14 @@ int key;
       break;
     case RC_SLEEP:
       break;			/* Already handled */
+    case RC_ALIAS:
+      if (argc > 2 )
+          AddAlias( args[0], args[1], args+2, argc-2);
+      if (argc == 2 )
+        AddAlias( args[0], args[1], NULL, 0);
+      if ( argc == 1 )
+        DelAlias( args[0] );
+      break;
     case RC_TERM:
       s = NULL;
       if (ParseSaveStr(act, &s))
@@ -4254,12 +4276,57 @@ int key;
 }
 
 void
+DoAlias( argv, argl )
+char **argv;
+int *argl;
+{
+  struct action act;
+
+  /* Find the alias */
+  struct alias *alias = FindAlias( *argv );
+
+  if ( alias == NULL )
+  {
+    Msg(0, "internal error alias not found" );
+    return;
+  }
+
+  act.nr = FindCommnr( alias->alias_value);
+
+  if ( act.nr == RC_ILLEGAL )
+    {
+      Msg(0, "illegal alias value - aliases to aliases don't work (yet).");
+      return;
+    }
+  if ( alias->alias_arg_count > 0 )
+    {
+      act.args = alias->alias_args;
+      act.argl = &(alias->alias_arg_count);
+    }
+  else
+    {
+      act.args = argv + 1;
+      act.argl = argl + 1;
+    }
+
+  DoAction(&act, -1);
+}
+
+
+void
 DoCommand(argv, argl) 
 char **argv;
 int *argl;
 {
   struct action act;
 
+
+  /*
+   *Alias?
+   */
+  if ( FindAlias( *argv ) != NULL )
+      return DoAlias( argv, argl );
+
   if ((act.nr = FindCommnr(*argv)) == RC_ILLEGAL)  
     {
       Msg(0, "%s: unknown command '%s'", rc_name, *argv);
@@ -6413,6 +6480,130 @@ char *presel;
   return wi;
 }
 
+
+
+/**
+ * Add an alias
+ */
+void AddAlias( name, value, args, count )
+     const char *name;
+     const char *value;
+     char **args;
+     int count;
+{
+  struct alias *new = NULL;
+
+  /* Make sure the alias maps to something */
+  if ( FindCommnr( (char *)value ) == RC_ILLEGAL )
+    {
+      Msg(0, "illegal alias value - aliases to aliases don't work (yet).");
+      return;
+    }
+
+  /* Make sure we don't already have this alias name defined. */
+  if ( FindAlias( (char *)name ) != NULL )
+    {
+      Msg(0, "alias already defined: %s", name);
+      return;
+    }
+
+
+  new = (struct alias *)malloc(sizeof(struct alias));
+
+  /* store it */
+  new->next        = NULL;
+  new->alias_name  = strdup( name );
+  new->alias_value = strdup( value );
+  new->alias_arg_count = count;
+  new->alias_args = NULL;
+
+  if ( count >0)
+  {
+    int i;
+    new->alias_args = (char **)malloc(sizeof(char *)*count+1);
+    for ( i = 0; i< count; i++ )
+      {
+        new->alias_args[i] = strdup( args[i]);
+      }
+    new->alias_args[i] = NULL;
+  }
+
+  /* Add to head */
+  {
+    new->next = g_aliases_list;
+    g_aliases_list = new;
+  }
+}
+
+
+/**
+ * Find an alias.
+ */
+struct alias *
+FindAlias( name )
+     char *name;
+{
+  struct alias *t = g_aliases_list;
+
+  while( t != NULL )
+    {
+      if ( ( t->alias_name != NULL ) &&
+           ( strcmp(t->alias_name, name) == 0 ) )
+        return t;
+
+      t = t->next;
+    }
+
+  return NULL;
+}
+
+
+
+/**
+ * Delete an alias
+ */
+void DelAlias( name )
+     const char *name;
+{
+
+  /* Find the previous alias */
+  struct alias *cur  = g_aliases_list;
+  struct alias *prev = g_aliases_list;
+
+  while( cur != NULL )
+    {
+      if ( ( cur->alias_name != NULL ) &&
+           ( strcmp(cur->alias_name, name) == 0 ) )
+        {
+          struct alias *found = cur;
+          int c;
+
+          /* remove this one from the chain. */
+          prev->next = found->next;
+
+          free( found->alias_name );
+          free( found->alias_value );
+          if ( found->alias_arg_count > 0 )
+            {
+              for ( c = 0; c <= found->alias_arg_count ; c++)
+                free(found->alias_args[c] );
+              free(found->alias_args);
+            }
+          free( cur );
+
+          Msg(0, "alias %s removed", name );
+
+        }
+      prev = cur;
+      cur = cur->next;
+    }
+
+  Msg(0, "alias %s not found", name );
+
+}
+
+
+
 #if 0
 
 /* sorted list of all commands */

Reply via email to