8

I have a script that allows me to log random thoughts while working on a project. In the terminal I would add a new log entry by running

$ @ "some random thought"

where @ is just an alias for my script.

Say my terminal is in this state:

$ ls /var/tmp
somefile.ext
another-file.l
$ _

After running my script, it would look like this:

$ ls /var/tmp
somefile.ext
another-file.l
$ @ "some random thought"
$ _

Now, I do not want that line ($ @ "some random thought") to stay on the screen after I enter it. I just want the script to run and leave no trace on the screen (some things are personal and some people might see my terminal). I also do not want to clear the entire screen.

Do you think this is possible? I am using Iterm2 if this helps.

NB: I know how to handle history so that it doesn't record my log entries. I just want to leave no trace on the screen.

whonoes
  • 193

4 Answers4

8

Instead of having a command to enter your thought, you could define a widget for that. In zsh:

thought() { 
  print -r -- $BUFFER >> ~/.thoughts
  # or: your-script $BUFFER
  BUFFER=
  zle -M 'thought recorded'
}
zle -N thought
bindkey '^T' thought

Then press Ctrl-T to add the content of the buffer to your ~/.thoughts file and clear it afterwards (BUFFER=). Then, you don't have to worry about quoting.

Another approach could be to use interactive comments:

setopt interactive_comments
alias '@=:;#'
preexec() {
  [[ $1 = @* ]] && {
    print -r -- ${1#* } >> ~/.thoughts
    # or: your-script ${1#* }
    echoti cuu1
  }
}

Again, no problem with quoting, but that only works for single line thoughts. (the echoti cuu1 takes care of clearing that line by moving the cursor up).

  • Doesn't this sidestep the question...? – jmetz Dec 17 '13 at 12:47
  • Thanks Stephane, but I already have a working script (python) which does a little more than logging strings. Your solution means I have to trash all out and it's a bit convoluted for my simple case :) Mutzmatron's answer solved my issue. – whonoes Dec 17 '13 at 13:05
  • I upvoted this answer after posting mine because I think it's less kludgy than a terminal hack. But there's no accounting for taste! – Alexios Dec 17 '13 at 13:44
  • @whonoes, just add a call to "your-script" in there, the print >> ~/.thoughts was just an example so that anybody can test it. – Stéphane Chazelas Dec 17 '13 at 14:39
  • @stephane, this indeed is a more elegant solution; I just want to solve everything in my script (which is too simple to have a widget as a dependency when I can avoid that, even by employing a terminal hack) – whonoes Dec 20 '13 at 08:44
6

Warning, this is a horrible, horrible hack (but then, the entire request is a bit of a hack). :)

Here's something that'll work on most terminals, including the braindead MS-DOS ‘ANSI.SYS’ emulator. Won't work on dumb terminals, of course (but nothing will):

tput sc
echo "This will be hidden."
sleep 5
tput rc; tput cuu 1; tput ed

Obviously, this is an example. Get rid of the echo and sleep and replace it with your command. Here's how it works:

  • tput sc saves the current co-ordinates of the cursor on-screen,
  • tput rc moves the cursor back to the stored co-ordinates. Now, the screen may have scrolled, so the sensitive stuff will be on the line above the saved one. So,
  • tput cuu 1 moves the cursor one row up. (if you feel especially paranoid, feel free to increase the number.
  • Finally, tput ed clears to the end of the screen (i.e. clears from the cursor to the end of line, then from the cursor to the bottom of the screen).

This will fail comically if the screen scrolls by a lot because sc doesn't know about scrolling, just screen co-ordinates.

tput is terminal-agnostic, so it'll work as long as your particular terminal is listed in the terminfo database and the TERM variable is correctly set.

Alexios
  • 19,157
4

You could try overwriting the previous line, which has already been answered;

How to change the contents of a line on the terminal as opposed to writing a new one?

For example (modified from original answer):

prompt% echo -n "Old line"; echo "\033[1A\033[1A" "new line"

Will display only:

prompt% new line

As the output. Adding more \033[1A sequences removes more lines.

Caveat: This doesn't work on all terminals.

jmetz
  • 281
  • My script does not output anything. I want to remove the actual command from the screen, not it's output. – whonoes Dec 17 '13 at 11:41
  • Yes, that will overwrite the last script output line; with your example, I would like for prompt% echo -n "Old line"; echo -e "\e[0K\r new line" to dissapear from the terminal. – whonoes Dec 17 '13 at 12:08
  • You're right, I updated my answer with the correct terminal sequence. – jmetz Dec 17 '13 at 12:13
  • Your current answer doesn't work for me now, it only prints out prompt % echo -n "Old line"; echo "\033[1A\033[1A" "new line" Old line\033[1A\033[1A new line prompt %, though I can't get the newlines to show up in comment. –  Dec 17 '13 at 12:34
  • e.g. it just prints some stuff and new prompt comes to new line. –  Dec 17 '13 at 12:36
  • @RistoSalminen: This works on my terminal; unfortunately the exact character codes to use may differ on different terminals, and I can't provide answers for other setups – jmetz Dec 17 '13 at 12:37
  • So it means that this answer is not very portable. –  Dec 17 '13 at 12:37
  • Correct; and my suspicion is that there is no universally portable answer. – jmetz Dec 17 '13 at 12:38
  • I agree with you. –  Dec 17 '13 at 12:38
  • This doesn't still remove the latest line, e.g. when user runs f.ex. ps, it prints new line which you cannot remove in any way. –  Dec 17 '13 at 12:43
  • 1
    Thank you mutzmatron, this solves my issue. One caveat would be that if the string I pass to the script has more than one line (the text wraps in the terminal), only the last one will be deleted. Adding more \033[1A sequences would work, but then if I add a string with just one line, more than one line will be removed from the terminal. Still, good enough for my case, I will accept your answer, thanks! – whonoes Dec 17 '13 at 13:00
  • 1
    I just posted the answer I was composing, and you beat me to it. My own solution uses tput, not terminal directives, so it's more portable across terminals. It works with multi-line output, too — but it breaks if the output scrolls a lot. – Alexios Dec 17 '13 at 13:45
  • @Alexios: You're right, tput is probably a better way to go - just upvoted your answer – jmetz Dec 17 '13 at 14:34
  • Thanks for the upvote — ‘Better’ is a bit relative... changing TERM makes it not work, for instance. But this whole thing is a kludge. :( – Alexios Dec 17 '13 at 14:51
0

Well, if it's just some random thought rather than actual command, then you can do so by adding space before the thought. It will exclude this command from getting into history

satish@Satish:/tmp $ echo "I'm in history"
I'm in history
satish@Satish:/tmp $  echo "I'm not"
I'm not
satish@Satish:/tmp $ history | tail -n 3
 1887  sudo su -
 1888  echo "I'm in history"
 1889  history | tail -n 3
satish@Satish:/tmp $ 
SHW
  • 14,786
  • 14
  • 66
  • 101
  • 2
    The OP wants the command to not be present in the terminal, not the history. – jmetz Dec 17 '13 at 11:47
  • As mentioned in the question, history is not a problem, I can manage that. With your example, I would like this line satish@Satish:/tmp $ echo "I'm not" to be hidden from the terminal after I run it. – whonoes Dec 17 '13 at 12:09
  • Yeah...I got it....will see if I can find solution for this. And then will post here :) – SHW Dec 17 '13 at 12:19