zuba
zuba

Reputation: 1508

`xdotool type ` - randomly repeats characters

I'm writing a script to automate work environment preparation. I need to open 4 terminal windows, arrange them and execute commands in each of them.

It works, but sometimes I get nasty fails - xdotool type randomly repeats some characters:

rvm use ruby-1.99999999999999999999999999999999.3-p194@ro && rails c
~/my_src/ruby_apps/ro > rvm use ruby-1.99999999999999999999999999999999.3-p194@ro && rails c
ruby-1.99999999999999999999999999999999.3-p194 is not installed.
To install do: 'rvm install ruby-1.99999999999999999999999999999999.3-p194'
~/my_src/ruby_apps/ro > 

or in the other window:

tail -fn 100 looooooog/thin.0.log
~/my_src/ruby_apps/ro > tail -fn 100 looooooog/thin.0.log
tail: could not open «looooooog/thin.0.log» for reading: No such file or directory
tail: no more files
~/my_src/ruby_apps/ro > 

I guess it depends on CPU load, cause I have really big .bashrc processed by ATOM and its load is high during script processing.

I use wait and sleep and special order of open_lxterminal_execute_hold() function invocations in the script toexecute simple simple commands first. That minimizes errors, but doesn't prevent them at all.

What would you suggest to get stable result regardless of CPU load(whatever)? It would be great to get rid of sleeps as well.

#!/bin/bash
#
# prepares work environment for rails project

# Opens lxterminal with title if windows with such title
#   doesn't exist, executes command and stays open. 
#   Otherwise does nothing.
#
function open_lxterminal_execute_hold(){
  local winid=`xwininfo -name $title 2>/dev/null |grep 'Window id:' |cut -d" " -f4`
  if [ -n "$winid" ]; then
    echo "Window for title '$title' exists with '$winid'"
  else
    lxterminal -t $title 
    sleep 1
    wmctrl -i -a "$winid" # bring the window to front, activate
    wait
    xdotool type "$command"
    wait
    xdotool key Return # run the command
    wait
  fi
}

pkill devilspie
cd ~/my_src/ruby_apps/ro # TODO param
title='rails-commandline';     command='ls';                                    open_lxterminal_execute_hold
title='rails-development.log'; command='tail -fn 100 log/development.log';      open_lxterminal_execute_hold
title='rails-user_case';       command='tail -fn 100 log/thin.0.log';           open_lxterminal_execute_hold
sleep 5
title='rails-console';         command='rvm use ruby-1.9.3-p194@ro && rails c'; open_lxterminal_execute_hold
/usr/bin/devilspie -a 2>/dev/null & # arrange windows

UPDATE How to prevent xdotool repeating charatcers?

Upvotes: 5

Views: 2381

Answers (4)

alexeypetrenko
alexeypetrenko

Reputation: 288

You can use xte command line tool instead. It does the same job, but without random key stickiness.

Upvotes: 0

zuba
zuba

Reputation: 1508

Actually I found anoter solution. I discovered that I used an old version of 2009 year from ubuntu deb package. The latest version of xdotool I installed from sources allows a new command line param --delay <value> which if used with 0 --delay 0 prevents repeating characters. So the function looks as follows now:

function open_lxterminal_execute_hold(){
  local winid=`xwininfo -name $title 2>/dev/null |grep 'Window id:' |cut -d" " -f4`
  if [ -n "$winid" ]; then
    echo "Window for title '$title' exists with '$winid'"
  else
    lxterminal -t "$title" 
    sleep 1
    wmctrl -i -a "$winid" 
    xdotool type --delay 0 "$command"
    xdotool key Return
  fi
}

good luck guys!

Upvotes: 0

user1419445
user1419445

Reputation:

Here is another solution, tested and working on my Ubuntu 11.04 system:

#!/bin/bash

function open_lxterminal_execute_hold() {
  xwininfo -name $1 > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo "Window for title '$1' already exists"
  else
    t=$(tempfile)
    echo ". ~/.bashrc" > $t
    echo "$2" >> $t
    lxterminal -t $1 -e "$SHELL --rcfile $t" &
  fi
}

#pkill devilspie
#cd ~/my_src/ruby_apps/ro
open_lxterminal_execute_hold 'rails-commandline' 'ls'
open_lxterminal_execute_hold 'rails-development' 'tail -fn 100 log/development.log'
open_lxterminal_execute_hold 'rails-user_case' 'tail -fn 100 log/thin.0.log'
#open_lxterminal_execute_hold 'rails-console' 'rvm use ruby-1.9.3-pl94@ro && rails c'
#devilspie -a 2>/dev/null &

As you may notice, I've commented some lines for testing, so you should remove the trailing '#' from the commented lines before running the script on your system.
The trick I've used is to start in each terminal a new shell with the "--rcfile" option.
This way, there is no need to use the "xdotool", "wait" and "sleep" commands.

Upvotes: 2

unutbu
unutbu

Reputation: 880547

Here is a workaround which avoids xdotool altogether. On the positive side, I think it is fairly simple. On the negative side, it does not appear to work with lxterminal -- though it does work with other terminals such as xterm and gnome-terminal.

For what it's worth, here is the idea:

Let bashrc run the appropriate commands based on the value of the title environment variable:

You can do so by adding something like the following to your .bashrc:

case "$title" in
rails-development.log)
    ls
    ;;
rails-commandline)
    tail -fn 100 /var/log/syslog
    ;;
*)
    ;;
esac

And then in your script you can use

function open_terminal_execute_hold() {
  local winid=`xwininfo -name $title 2>/dev/null |grep 'Window id:' |cut -d" " -f4`
  if [ -n "$winid" ]; then
    echo "Window for title '$title' exists with '$winid'"
  else
    gnome-terminal -t "$title" &
  fi
}

cd /tmp # TODO param
export title='rails-commandline' &&  open_terminal_execute_hold &
export title='rails-blah' &&  open_terminal_execute_hold &
export title='rails-development.log' && open_terminal_execute_hold &

For some reason lxterminal seems to only use the first value for title, ignoring subsequent changes to its value.

Upvotes: 2

Related Questions