Simulate Typing with This C Program

I recently created a video demonstration of how to do some work at the command line, but as I tried to record my video, I kept running into problems. I'm just not the kind of person who can type commands at a keyboard and talk about it at the same time. I quickly realized I needed a way to simulate typing, so I could create a "canned" demonstration that I could narrate in my video.

After doing some searching, I couldn't find a command on my distribution that would simulate typing. I wasn't surprised; that's not a common thing people need to do. So instead, I rolled my own program to do it.

Writing a program to simulate typing isn't as difficult as it first might seem. I needed my program to act like the echo command, where it displayed output given as command-line parameters. I added command-line options so I could set a delay between the program "typing" each letter, with an additional delay for spaces and newlines. The program basically did this the following for each character in a given string:

  1. Insert a delay.
  2. Print the character.
  3. Flush the output buffer so it shows up on screen.

First, I needed a way to simulate a delay in typing, such as someone typing slowly, or pausing before typing the next word or pressing Enter. The C function to create a delay is usleep(useconds_t usec). You use usleep() with the number of microseconds you want your program to pause. So if you want to wait one second, you would use usleep(1000000).

Working in microseconds means too many zeroes for me to type, so I wrote a simple wrapper called msleep(int millisec) that does the same thing in milliseconds:


int
msleep (int millisec)
{
  useconds_t usec;
  int ret;


  /* wrapper to usleep() but values in milliseconds instead */


  usec = (useconds_t) millisec *1000;
  ret = usleep (usec);
  return (ret);
}

Next, I needed to push characters to the screen after each delay. Normally, you can use putchar(int char) to send a single character to standard output (such as the screen), but you won't actually see the output until you send a newline. To get around this, you need to flush the output buffer manually. The C function fflush(FILE *stream) will flush an output stream for you. If you put a delay() before each fflush(), it will appear that someone is pausing slightly between typing each character.

Here's a simple function I wrote to simulate typing. The echodelay() function takes parameters that describe the delay before printing characters, spaces and newlines. The last parameter is the string to print. The function loops through the string and pauses before printing each character, then flushes the output buffer. The effect is that each character seems to appear one at a time, as though someone were typing at a keyboard:


void
echodelay (int chdelay, int spdelay, int nldelay, char *string)
{
  int pos = 0;


  /* add a delay between printing each character in the string,
     depending on the character */


  do
    {
      switch (string[pos])
        {
        case '\0':             /* new line */
          msleep (nldelay);
          break;
        case ' ':              /* space */
          msleep (spdelay);
          break;
        default:               /* character */
          msleep (chdelay);
          break;
        }


      putchar (string[pos]);
      fflush (stdout);
    }
  while (string[pos++] != '\0');
}

With that function, it's a simple process to write a parent main() function to parse the command line, set the different delays, and call the echodelay() function to generate the output with the appropriate delays:


/* echodelay.c */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


void echodelay (int chdelay, int spdelay, int nldelay,
 ↪char *string);
int msleep (int millisec);
int atoipos (char *string);


int
main (int argc, char **argv)
{
  int opt;
  int chdelay = 0, spdelay = 0, nldelay = 0;


  /* parse command line */


  while ((opt = getopt (argc, argv, "c:s:n:")) != -1)
    {
      switch (opt)
        {
        case 'c':              /* -c nnn */
          chdelay = atoipos (optarg);
          break;
        case 's':              /* -s nnn */
          spdelay = atoipos (optarg);
          break;
        case 'n':              /* -n nnn */
          nldelay = atoipos (optarg);
          break;
        default:               /* unrecognized option */
          fprintf (stderr, "Usage: echodelay [-c millisec]
           ↪[-s millisec] [-n millisec] [text..]\n");
          exit (1);
          break;
        }
    }


  /* pass all remaining options as text to echodelay() */


  for (opt = optind; opt < argc; opt++)
    {
      echodelay (chdelay, spdelay, nldelay, argv[opt]);
      putchar (' ');
    }


  putchar ('\n');


  exit (0);
}


void
echodelay (int chdelay, int spdelay, int nldelay, char *string)
{
...
}


int
msleep (int millisec)
{
...
}


int
atoipos (char *string)
{
  int val;

  /* wrapper to atoi() but always a positive return value */


  val = atoi (string);


  if (val < 0)
    {
      val = 0;
    }


  return (val);
}

And compile it like this:


gcc -Wall -o echodelay echodelay.c

In a shell script, I had commands to print a "prompt", then simulate typing a command before executing the command—for example, this command to generate a file of random size in your /tmp directory:


echo -n 'prompt$'
echodelay -c 500 -s 1000 -n 2000 'ls -lh /tmp'
ls -lh /tmp

This is a fairly straightforward C program to simulate typing. I wrote it quickly to do a single job, but it works as a solution to simulate typing while I narrated my how-to video. In this way, I didn't need to think about what I was typing while I was trying to describe it. If you need to simulate typing for a similar task, I hope you find this program useful.

Jim Hall is an open source software advocate and developer, probably best known as the founder of FreeDOS. Jim is also very active in usability testing for open source software projects like GNOME. At work, Jim is CEO of Hallmentum, an IT executive consulting company that helps CIOs and IT Leaders with strategic planning and organizational development.

Load Disqus comments