0

I am trying to make a mac Clippy in bash. Here is some of my code:

say "Hello there!"

declare -a assist_array=()

while true; do
  if pgrep -xq -- "Mail"; then
      assist_array+=('It looks like your trying to send an email. Would you like some help?')
  fi

  if pgrep -xq -- "Notes"; then
      assist_array+=('It looks like your trying to take a note. Would you like some help?')
  fi

  arraylength=${#assist_array[@]}
  for (( i=0; i<${arraylength}+1; i++ )); do
    echo ${assist_array[i]}
    say ${assist_array[i]}
    assist_array=()
  done

done

When I have Mail open, it echos and says: "It looks like your trying to send an email. Would you like some help?" then a new line. I have both Mail and Notes open. How can I make it so it continues to scan for open apps and not get stuck in the for loop?

4
  • Wow! Three answers within 12 minutes of posting! I wish they had stack overflow when I started coding. Heck! I wish they had the internet when I started coding! Commented Oct 7, 2018 at 17:03
  • I know. Its wierd... Commented Oct 7, 2018 at 17:05
  • I ran it on my mac and I found it more annoying and less useful than the original clippy, so you have surpassed Microsoft. You may be interested in putting a sleep into your program to tone it down a little. Commented Oct 7, 2018 at 17:11
  • I did. This was just a clip of the program so the program could be replicated. Commented Oct 7, 2018 at 17:23

3 Answers 3

1

You're emptying the array during the loop. As a result, when the next iteration is attempted, there's nothing in ${assist_array[i]} to print. If you need to empty the array, do it after the loop finishes.

Also, array indexes go from 0 to length-1, not from 1 to length. And you should generally quote variables that may contain multiple words.

for (( i=0; i<${arraylength}; i++ )); do
    echo "${assist_array[i]}"
    say "${assist_array[i]}"
done
assist_array=()
Sign up to request clarification or add additional context in comments.

Comments

0
say "Hello there!"

declare -a assist_array=()

while true; do
  if pgrep -xq -- "Mail"; then
      assist_array+=('It looks like your trying to send an email. Would you like some help?')
  fi

  if pgrep -xq -- "Notes"; then
      assist_array+=('It looks like your trying to take a note. Would you like some help?')
  fi

  arraylength=${#assist_array[@]}
  for (( i=0; i<${arraylength}; i++ )); do
    echo ${assist_array[i]}
    say ${assist_array[i]}    
  done
  assist_array=()
done

Above code should work for you. The issue is that arrays are zero based, so your reference to assist_array[2] is actually an empty string. When you pass nothing to "say", it will read stdin.

Also, as the other answers have indicated (either explicitly or implicitly) you are initializing the array inside the for loop. You shouldn't do that in as much as you are not done reading it yet.

So, basically, your just stuck with say waiting for stdin. You can hit Ctrl-D to end the stdin input on your current program.

Comments

0

I see two issues in your code:

  • array indices start with 0 in Bash; your for loop is using 1 as the starting index
  • it's not OK modify the array inside the for loop; put the array reset command outside

#!/bin/bash
while true; do
  assist_array=() # reset the array
  if pgrep -xq -- "Mail"; then
      assist_array+=('It looks like your trying to send an email. Would you like some help?')
  fi

  if pgrep -xq -- "Notes"; then
      assist_array+=('It looks like your trying to take a note. Would you like some help?')
  fi

  arraylength=${#assist_array[@]}
  for ((i=0; i<arraylength; i++)); do
    echo "${assist_array[i]}"
    say "${assist_array[i]}"
  done

  # probably put a sleep here
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.