how to execute a function in i3 config? [closed] - i3

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
I want to rename a workspace but retain the workspace number by default, in i3 user guide, I find the following script to do so.
bindsym $mod+r exec i3-input -F 'rename workspace to "%s"' -P 'New name: '
But the problem is that it doesn't keep workspace number by default, so I have to remember to type the workspace number.
I've found a way to get the number of the focused workspace number with following command, but I don't know how to concat the number to with the input name together in i3 config.
i3-msg -t get_workspaces | jq '.[] | select(.focused == true) | .num'
So, I'm wondering whether in i3 config file, I can execute some kind of function to concat the workspace number with user input to achieve my purpose?

I don't think you can. But, you can always do whatever you want if you create a script and call it with exec in your i3-config. So, for example:
~/bin/i3-rename-workspace (or wherever is convenient for you):
N=$(i3-msg -t get_workspaces | jq '.[] | select(.focused == true).num')
i3-input -F "rename workspace to \"$N: %s\"" -P 'New name: '
Somewhere in your i3-config:
bindsym $mod+r exec i3-rename-workspace
Remember to provide the full path to your script, or put it somewhere in i3's $PATH.

You can execute a function from the i3 config, it gets a bit hairy but it works out quite nicely. The key things to remember are any commands with a , or ; need quoted (i.e. every function you can possibly write as it is a required part of the syntax), and if you have additional quotes of the same type inside the command passed to exec you need to escape them with \\ per the i3 documentation.
Personally I wanted a simple shutdown menu without having to create a separate script to maintain and drag around outside my i3 config, I used an inline function definition and call. This is very similar to the recommended way to run external commands in git aliases (and is where I had the idea that it would work).
bindsym $mod+Shift+q exec "bash -c 'f () { res=$(rofi -dmenu < <(echo -en \\"logout\nrestart\nshutdown\\")); case $res in logout) i3-msg exit;; restart) sudo shutdown -r +2;; shutdown) sudo shutdown -P +2;; esac; }; f;'"
This is a bit dense to unpack, but I define the temporary function f () {...}; f;' and call it after. Inside the function I'm feeding in the options to the menu using process substitution and input redirection to capture the selection to a variable res=$(rofi -dmenu < <(echo -en \\"logout\nrestart\nshutdown\\")) and note the extra \\ to escape the inner double quotes.
Finally I'm evaluating the option the user selected via case and choosing an action based on that option, with a 2 minute timeout on the restart and shutdown commands so I can abort if somehow I hit the hard to accidentally hit modifiers required to trigger the menu AND select an item rather than just pressing Esc to exit the menu.
After writing this up and realizing how easy it might be to logout and loose all my current windows/layouts, I'm going to add a "no-op" option that appears first in the list and is evaluated last in the case statement that maybe will echo something funny via cowsay or notify-send.

Related

how to append one element to a GNU bash array variable and use that array variable as arguments to an ELF executable [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
In the Bismon static source code analyzer (GPLv3+ licensed, git commit 49dd1bd232854a) for embedded C and C++ code (using a plugin for GCC 10 straight compiler on Debian bookworm for x86-64) I have a test Bash script Hello-World-Analyze which uses a GNU array variable bismon_hello_args.
That variable is declared (at line 56) using:
declare -a bismon_hello_args
and I would like to fill that bismon_hello_args array variable from script arguments starting with --bismon, and later invoke the bismon executable (compiled from C source files) with several arguments to its main being the elements of that bismon_hello_args array variable.
So if my Hello-World-Analyze script is invoked as Hello-World-Analyze --bismon-debug-after-load --bismon-anon-web-cookie=/tmp/bismoncookie --gcc=/usr/local/bin/gcc-11 I want the bismon ELF executable to be started with two arguments (so argc=3, in C parlance) : --bismon-debug-after-load followed by --bismon-anon-web-cookie=/tmp/bismoncookie
For some reason, the following code (lines 58 to 64) in that Hello-World-Analyze script:
for f in "$#"; do
case "$f" in
--bismon*) bismon_hello_args+=$f;;
--asm) export BISMON_PLUGIN_ASMOUT=/tmp/gcc10_metaplugin_BMGCC.s;;
--gcc=*) export BISMON_GCC=$(echo $f | /bin/sed -e s/--gcc=//);;
esac
done
does not work as expected. It should be (and was in a previous git commit e8c3d795bc9dc8) later followed with
./bismon $bismon_hello_args &
But debugging prints show that bismon is invoked with argc=2 so one long argv[1] program argument...
What am I doing wrong?
Merely += adds a string to an existing string. You probably want bismon_hello_args+=("$f");; (notice also the quotes). To call the program, use ./bismon "${bismon_hello_args[#]}" & (notice the quotes, again).
The syntax to use an array variable is different than the syntax for simple scalars. This syntax was inherited from ksh, which in turn needed to find a way to introduce new behavior without sacrificing compatibility with existing Bourne shell scripts.
Without the array modifiers, Bash simply accesses the first element of the array. (This confuses beginners and experienced practitioners alike.)

What does "rc=$$? ; cat File1 >/proc/self/fd/2 ; exit $$rc" comand do in linux shell? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Please help me understand the following command completely:
python3 code.py >result.txt 2>&1 || ( rc=$$? ; cat result.txt >/proc/self/fd/2 ; exit $$rc )
In the above code, I couldn't find out what rc=$$? and $$rc mean.
IMO, the code does not make much sense. If you try by yourself on the command line the following:
false; rc=$$?; echo $rc; echo $$rc
you will see that the first echo outputs some number, followed by a question mark, and the second number outputs the same number, followed by the letters rc.
The reason is that $$ is a special variable maintained by bash, which holds the current process id. While there is also a variable which holds the exit code of the most recently executed command, it is named $?, but never referenced in the code you posted. Hence, the shell will, in general, assign to the variable rc a string containing the PID, and simply add the subsequent ? to it.
I said in general, because there is an exception, just it is highly unlikely to occur. The reason is that ? is also a valid wildcard pattern in globbing, and matches any character. Now let's assume that the PID of your shell is 4711, and in the current working directory happens to be a file with name 4711x. The $$? would be 4711?, the ? would match the x, and rc would end up with the name 4711x instead of 4711?. The result would be even funnier, if you had two similar files, 4711x and 4711y. Try it!
The exit $$rc is even more bizarre. As explained before, $$rc expands to something like 4711rc, and exit 4711rc is simply illegal; you would get an error message bash: exit: ...: numeric argument required
From this, I think that either whoever wrote this code, never debugged it, or you made some mistake when copying and pasting it into this question.
In Bash $$ is the process ID and ? is used to find the return value of the last executed command. So basically this fetches process ID and assign it a variable rc. Then it looks like exit with code equals to process ID.

How to remove comments of ASM code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have an directory with about 300 source code in ASM.
So, I need to remove the comments (";") of this codes.
Until now, I removed the comments of 3 files, where each file has 100 lines of code.
Somebody know a script that can help me?
Sed is your friend:
find <asm_dir> -type f | xargs sed -i -e '/^;/d' -e 's/^\([^;]*\);.*$/\1/'
The first expression deletes lines that begin with the comment character ;. The second expression strips inline comments (from ; to the end of the line).
You can simply accomplish this in e.g. Vim or Emacs. I'm going to discuss Vim here.
Assuming you have all your .asm files in one directory go to your shell and do something like
cd /path/to/my/files
gvim *.asm
This will open all your .asm files for editing in gvim (graphical vim). If you are not familiar with Vim it's a great text editor and we are going to record a macro to do our job. Only do what I say or you will mess things up :) To be on the safe side you should backup your files in case you mistype something and delete more than you wish to.
Type these characters (or press the appropriate thing on your keyboard as specified in <>'s):
qa:g/^\s*;/d<Enter>:n<Enter>q
This will start recording a macro [q], store it in [a], execute a global deletion of every line in the first file that starts with optional whitespace followed by a semicolon [:g/^\s*;/d<Enter>], move to the next file [:n<Enter>] and save the macro [q]. All you have to do now is run this macro as many times as you have files left. You can either get this by running ls *.asm | wc -l in your directory with the saved files or you can simply overshoot it and input a larger number, Vim will stop on the last file and notify you there's no more files to edit. So with the overshooting example you could type
1000#a
and the macro will start running through all the files. This may take some time so be patient. Once it's done we still haven't saved our files so we could check the results before commiting to them. You can check a couple of files if they look OK and if yes type
:wa<Enter>
All your files are saved now and you can exit Vim with ZQ or :q<Enter>.

bash auto complete [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
Command completion in bash(1) is quite handy; I like this feature very much. But I have a question.
For example, we all have Documents and Downloads in $HOME directory.
So if I input cd ~ and then press TAB, then it will traverse all the directory under $HOME. When Documents come up and the shell now displays cd ~/Documents, I want to go deeper into this directory. For example, there is a work directory in Documents. My intention is to cd to the work directory.
So what should I do?
I usually input a w then press TAB, but when this action repeats too much I found it quite annoying. And sometimes I don't know exactly what files are under this directory.
Do you have any good ideas?
ps: In fact, i met this problem when i was using vim. I input :e then TAB, it will cycle the subfolders, the only way i found to stop the cycling and enter the next level is input a /. So the path has double '/' in the end.
You could switch your shell to ZShell, which allows you to tab through directories without typing the first letter.
For example, you can type
cd ~/
Pressing TAB will bring up a list of all subfolders (like in bash), but pressing TAB multiple times will allow you to cycle through the subfolders. Pressing the -> or / key will allow you to start tab-completing inside that directory, and so on.
You can sometimes use chsh (man chsh for more info) to change your shell, if it's your own personal machine, or your network might have a special way to change your shell. You might also want to Google for some common .zshrc / .zshenv settings or migrate your old .bashrc / .cshrc / .profile settings.
Zsh also has ways to set up TAB completion for other tasks, for example, it can TAB complete svn files based on those that aren't already in SVN (for svn add). To get these features, add
autoload -U compinit
compinit
to your .zshrc file. There are plenty more ways to customize your TAB completion in zsh (such as with case-insensitivity, or for arguments to different programs), but if you're interested in those, you can probably find more information than I know by searching.
Like the Jack Toole's zsh suggestion (which is a perfectly fine shell), if you have to use bash, you can stick this in your .bashrc for the same "continue to hit tab cycle through possibilities" feature:
test -n "$PS1" && bind TAB:menu-complete
There's also a project called bash-completion that provides a lot of other kinds of completion other than pathname completion.
If you don't know what is in the directory, just press TAB one more time.

Clear a terminal screen for real [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 1 year ago.
Improve this question
Using the clear command on the terminal only fools the user into thinking the screen has been cleared...you can still see output from the previous commands when you scroll using the mouse. This makes life difficult when you are drowning in a tsunami of text.
Various solutions (escape code etc.) which can be found on the Internet are only variations of what the clear command already does.
So how do you clear the contents of a terminal in Linux for real?
Use the following command to do a clear screen instead of merely adding new lines ...
printf "\033c"
yes that's a 'printf' on the bash prompt.
You will probably want to define an alias though...
alias cls='printf "\033c"'
Explanation
\033 == \x1B == 27 == ESC
So this becomes <ESC>c which is the VT100 escape code for resetting the terminal. Here is some more information on terminal escape codes.
Edit
Here are a few other ways of doing it...
printf "\ec" #\e is ESC in bash
echo -en "\ec" #thanks #Jonathon Reinhart.
# -e Enable interpretation of of backslash escapes
# -n Do not output a new line
KDE
The above does not work on the KDE console (called Konsole) but there is hope! Use the following sequence of commands to clear the screen and the scroll-back buffer...
clear && echo -en "\e[3J"
Or perhaps use the following alias on KDE...
alias cls='clear && echo -en "\e[3J"'
I got the scroll-back clearing command from here.
Try reset. It clears up the terminal screen but the previous commands can be accessed through arrow or whichever key binding you have.
tput reset
That will do the trick!
None of the answers I read worked in PuTTY, so I found a comment on this article:
In the settings for your connection, under "Window->Behavior" you'll find a setting "System Menu Appears on ALT alone". Then CTRL + L, ALT, l (that's a lower case L) will scroll the screen and then clear the scrollback buffer.
(relevant to the OP because I am connecting to an Ubuntu server, but also apparently relevant no matter what your server is running.)
Clean the visible screen
clear
Clean screen and clear buffer
clear && clear
Clean and 1-sec delay
reset
Clean without 1-sec delay
tput reset
My favorite human friendly command for this is:
reset
Tested on xterm and VT100. It also helps after an abnormal program termination.
Keeps the command buffer, so up-arrow will cycle through previous commands.
I know the solution employing printing of new lines isn't much supported, but if all else fails, why not? Especially where one is operating in an environment where someone else is likely to be able to see the screen, yet not able to keylog. One potential solution then, is the following alias:
alias c="printf '\r\n%.0s' {1..50}"
Then, to "clear" away the current contents of the screen (or rather, hide them), just type c+Enter at the terminal.
The following link will explain how to make that alias permanent so you don't have to keep typing it in.
https://askubuntu.com/questions/17536/how-do-i-create-a-permanent-bash-alias
These are the steps detailed at that link.
vim ~/.bashrc or gedit ~/.bashrc or what ever text editor you like
put alias cls='printf "\033c"' at the bottom of the file
save and exit
. ~/.bashrc (and yes there should be a space between . and ~)
now check to see if everything worked!
I take no credit for this information just passing it along.
Just to add that tmux scroll buffer does not clear with clear, reset or printf. You need to :clear-history. See link.
With KDE and Ubuntu 12.04 LTS and the "Konsole" terminal, none of the posted answers work. However, pressing default keyboard shortcut CTRL+Shift+X does work! Source:
https://bugs.kde.org/show_bug.cgi?id=288913
echo -e "\e[3J"
This works in Linux Machines
Compile this app.
#include <iostream>
#include <cstring>
int main()
{
char str[1000];
memset(str, '\n', 999);
str[999] = 0;
std::cout << str << std::endl;
return 0;
}

Resources