I often run Vim in a tmux session to I can run tests in an adjacent pane. On a smaller monitor, I either have to sacrifice more Vim screen real estate than I'd like, or make the test pane too small to read the full results (which is fine if everything passes, but not when there are failures and I need to see the details).
Then my workflow becomes:
trigger tests from within Vim
switch to test pane (last-pane)
zoom pane to occupy full window (resize-pane -Z)
read the results
restore original layout (resize-pane -Z)
switch back to Vim pane (last-pane)
I wanted to add a key binding that I could use when I'm in the Vim pane to zoom the test pane (hiding Vim), and be able to use the same binding once zoomed to restore the original layout, returning me to Vim. This is what I came up with, but I wonder if there's a better way I can do it. I had to set, check, and unset an environment variable to save the state that would support toggling back and forth with the same key binding. I also haven't figured out how to make the toggle state specific to a window (right now, any multi-window session shares the state across all its windows, so this doesn't work correctly)
bind Space if-shell '[ -z "${ALT_PANE_ZOOM+x}" ]' \
'select-pane -t :.+; resize-pane -Z; set-environment ALT_PANE_ZOOM 1' \
'set-environment -u ALT_PANE_ZOOM; last-pane'
Update:
I found a simpler solution. Rather than relying on a per-window environment variable, I can leverage -F and the window_zoomed_flag format variable:
bind Space if-shell -F '#{window_zoomed_flag}' \
'last-pane' \
'select-pane -t :.+; resize-pane -Z'
In your tmux.conf, create a keybind which:
Saves the zoom state
Switch to the last pane, unzooming if a pane was zoomed in
Conditionally zooms depending on the zoomed state in #1
-
bind key run-shell "tmux setenv zoomed $(tmux display -p '#{window_zoomed_flag}')"\; \
last-pane\; \
run-shell "test $(tmux display -p '#{zoomed}') -ne 0 || tmux resize-pane -Z"
Note that the backslash escapes on the semicolons command separators are required.
Related
So, I have setup my .zshrc to have a basic level of syntax checking by creating bindkey lines for basically all character generating keys and pointing them to respective functions that both generate the character and then call the syntax checker.
It is otherwise working perfectly, however I want to apply it to tab so that it will take into account $BUFFER changes from compinit, however calling compinit manually within the trap_tab function I created doesn't even call compinit.
Any help is much appreciated!
Below is the relevant bit. Just uncomment and recomment the bindkey and zle -N lines. When uncommented, even though compinit is called, I do not receive any autofill options when hitting tab.
# Setup basic config stuff for history size, Vim keybindings, and the like
HISTFILE=~/.histfile
HISTSIZE=1000
SAVEHIST=1000
setopt extendedglob notify
unsetopt nomatch
# Auto-completion (double-tab tab)
zstyle :compinstall filename '/home/terminus/.zshrc'
autoload -Uz compinit
compinit
zstyle ':completion:*' menu select
function trap_tab
{
compinit
}
#bindkey ' ' trap_tab
#zle -N trap_tab
export EDITOR='vim
Turns out there is no "proper" solution, however at least one guy on GitHub figured out a self-described "hacky" solution which does appear to do what I want, albeit with some additional formatting needed: github.com/Valodim/zsh-capture-completion
Background.
I am a frequent vim-user, I just love the way you can navigate the buffers without ever having to reach for the mouse. I'm especially fond of the relative line numbers that let's me jump to specific lines with perfect accurecy, it just makes navigating that much faster. I also use tmux quite a bit since I often have a lot of stuff going on in my terminal.
The thing that bugs me the most though is when I use tmux copy-mode, it just takes forever to navigate to the line(s) you want to copy if you are using the arrow-keys, ctrl+p or k.
Searching for a unique keyword in the buffer is also not ideal but it might be faster if you already know what to search for. A lot of the time you make a search only to discover that the keyword you searched wasn't so unique after all and you didn't end up on the line you wished for anyway.
My question is this:
Does tmux support relative line-numbers?
..or line-numbers at all for that matter?
I can't find any information about this on the web. Nobody seems to be mentioning anything about this anywhere. Is there a better way?
Any other tips for ultra-speedy navigation in tmux copy-mode using the keyboard would also be very much appreciated.
tmux has a linenumber system in copy mode. however the first line is very bottom line.
In copy mode you can press : to go to line but there is no option to show linenumber. You can use some vim motions (key-mode was set as vi) in copy-mode, e.g. j k 20j 20k f F t T gg G 20G H L M ^ $ / ? ctrl-u ctrl-d w b ....
I think for copy a block of text, it is enough.. If you think you still cannot "ultra-speedy navigation", make a scenario, let's see how could we copy faster.
check man-page of tmux for details.
I found this tip. It will take you to your line with less keystrokes.
# super fast way to reach copy-mode and search upwards
bind-key / copy-mode \; send-key ?
This is a total hack but it works:
tmux split-window -h -l 3 -b "printf '\e[38;5;0m\e[48;5;226m' \
&& seq 200 1 \
&& echo -n 0 \
&& read" \
&& tmux select-pane -l
(newlines added for readablitiy)
To break this down:
tmux split-window -h -l 3 "command..." splits the pane -h horizontally (that is places a new pane next to the current one rather than above or below) with a -l width of 3 (you're unlikely to need more than 3 digits of line number... 0-999) to the -b left of the current pane and runs the command in it:
printf ... just sets the background colour to yellow and the foreground colour to black... You can omit this bit if you're not feeling fancy :)
seq 200 1 prints line numbers from 200 to 1 - extend if you have a tall screen!
echo -n 0 prints the 0 on the last line, because seq will print a trailing newline and we don't want that
read waits for you to press enter - this is how we block it from closing after the echo has completed
tmux select-pane -l jumps you back to focus on the pane you were working on
Select the pane and press enter to close it.
I would imagine that you can do something add a name for the new pane and create a keybinding for both opening and closing it from the pane you're actually trying to count line numbers on, but for now I'm just using the binding:
bind N split-window -h -l 3 -b "printf '\e[38;5;0m\e[48;5;226m' && seq 200 1 && echo -n 0 && read" \; select-pane -l
I want to change top panel color and alpha when any window is maximized.
For now I have something like this:
#!/bin/bash
while [ 1 = 1 ]
do
if window_is_maximized
then
xfconf-query -c xfce4-panel -p /panels/panel-0/background-alpha -s 100
else
xfconf-query -c xfce4-panel -p /panels/panel-0/background-alpha -s 50
fi
done
Maximized windows in X do not have a special state that you can test reliably. From a script, you can use xwininfo:
You can check if the window happens to be the same size as the root (main) window, and its position is the upper-left corner.
If you happen to be using a window manager which supports certain EMWH properties (_NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), your script could check for those. But in a quick check for window managers which might do that, I found none.
I'm looking for a way to create keyboard shortcuts in Linux using backtick (`) / tilde (~) key and some other key. In an ideal case:
pressing tilde down does nothing
pressing another key while the tilde is pressed down triggers a (customizable) shortcut
when releasing the tilde before/without pressing another key, just send the tilde keystroke.
I have something similar in AutoHotKey for Windows, and i've been searching for a way to recreate this in a (any) Linux environment. I would consider using any GUI if i could get this working, but of course a more "general" solution would be even better.
I think i finally got it!!
I use xmodmap to turn the grave key into the modifier Hyper_L, and XCape to send the grave if the key is released without another key being pressed.
Xcape was intended to open the app menu ("Start menu") when the meta-key ("windows key") is pressed and released without another key, so as an added bonus, it does that too. Meaning you can both use Meta as a modifier, like Meta-F to open the file manager AND use the meta-key seperately to open the whiskers menu.
If all is right, you can open the keyboard settings manager using ~-k, and you can make new shortcuts using the ~-key. Because that's still tiresome and not easily portable between different systems, i've included some shortcuts using xfconf-query, which will probably only work in Xfce.
Here's the basics of my script:
#!/bin/sh
# reset pretty much ALL keyboard settings
setxkbmap
# Free up the mod3 and mod4 flags from all keys it may be associated with:
xmodmap -e "clear mod3"
xmodmap -e "clear mod4"
# Add Hyper_L to the grave key (49)
xmodmap -e "keycode 49 = Hyper_L asciitilde grave asciitilde"
# You need a grave key somewhere else (!) so, bind it to an unused key:
xmodmap -e "keycode 250 = grave"
# Restore Mod4 but without Hyper_L (which was at location 4)
xmodmap -e "add mod4 = Super_L Super_R Super_L"
# Assign the mod3 to Hyper_L:
xmodmap -e "add mod3 = Hyper_L"
dist=100
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>Right -s "xdotool mousemove_relative -- $dist 0" --create -t string
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>Down -s "xdotool mousemove_relative -- 0 $dist" --create -t string
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>Left -s "xdotool mousemove_relative -- -$dist 0" --create -t string
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>Up -s "xdotool mousemove_relative -- 0 -$dist" --create -t string
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>space -s "xdotool click 1" --create -t string
/usr/bin/xfconf-query -c xfce4-keyboard-shortcuts -p /commands/custom/\<Hyper\>k -s "xfce4-keyboard-settings" --create -t string
# (re)starting xcape to produce a ` after key-up if no other key was pressed
killall xcape
xcape -t5000 -e "#49=grave;Super_L=Control_L|Escape" &
A more extended version of the script, with some more shortcuts can be found here.
I am not sure if it will work out for you but you should check:
xdotool (http://manpages.ubuntu.com/manpages/precise/man1/xdotool.1.html)
zenity (http://manpages.ubuntu.com/manpages/precise/man1/zenity.1.html)
Both these tools let you create some custom actions and shortcuts.
Here is an example of xdotool: https://askubuntu.com/questions/212154/create-a-custom-shortcut-that-types-clipboard-contents
Hope it helps and good luck :)
Bruno
After switching to Ubuntu on another machine, I also wanted to use tilde as a modifier key the way I use it in my AHK scripts.
I did quite some research on different tools for ex. xdotool, xev, autotools, xbindkeys and so on and finally found a solution to that. Here are the steps.
Install Autokey, python, python evded module, xte(sudo apt-get install xautomation).
Read a little about Autokey and how it launches python scripts or create hotstrings. In Autokey, we can set a hotkey to call a python script. So you can assign the python script down below to your tilde key or for that matter whatever custom hotkey you plan to create.
Here is the required custom functionality(thought not yet completely ported to linux, I have it scripted in autohotkey and just love it. It keeps the hand glued to keyboard ;))
Tilde + Up arrow: Move mouse pointer upwards by 100 positions
Tilde + Down arrow: Move mouse pointer downwards by 100 positions
Tilde + Right arrow: Move mouse pointer to right by 100 positions
Tilde + Left arrow: Move mouse pointer to left by 100 positions
Tilde + Enter: Left Mouse click (not present in the python script)
Tilde + Alt + Enter: Right Mouse Click
I use the tilde (KEY_GRAVE) as my modifier key. When this key is pressed, Autokey launches the python script. The scripts runs a loop until the tilde key is released. In the loop, the script keeps on detecting the keyboard inputs. On a UP arrow key(KEY_UP) press, the script sends a command to move a mouse by relative position (0, -100) utilizing 'xte' and so on.
from evdev import InputDevice, categorize, ecodes
from select import select
dev = InputDevice('/dev/input/event4')
releasekey = False
while releasekey==False:
r,w,x = select([dev], [], [])
for event in dev.read():
if event.type == ecodes.EV_KEY:
#system.exec_command("xte 'mousermove 0 3'", False)
#break
if event.code == ecodes.KEY_UP:
if event.value == 1:
system.exec_command("xte 'mousermove 0 -100'", False)
if event.code == ecodes.KEY_DOWN:
if event.value == 1:
system.exec_command("xte 'mousermove 0 100'", False)
if event.code == ecodes.KEY_RIGHT:
if event.value == 1:
system.exec_command("xte 'mousermove 100 0'", False)
if event.code == ecodes.KEY_LEFT:
if event.value == 1:
system.exec_command("xte 'mousermove -100 0'", False)
if event.code == ecodes.KEY_GRAVE:
if event.value == 0:
releasekey = True
break
You have to adjust the dev = InputDevice('/dev/input/event4') line to assign the correct name of your keyboard. In my case, event4 is my keyboard. Yours might be different. You can check out the handy tutorial "Reading Events" on python-evdev. That code actually outputs the name of your keyboard listed under /dev/input. Actually, my script is an extention to that tutorial script.
The only problem is that the python script must be started as a root user otherwise the keyboard input device can not be accessed. You can overcome this by creating a udev rule file which changes the permission of the device to make it available for reading writing eg. create a rule file and add this line
KERNEL=='event4', MODE="0660" and load the rule . At the end you must add yourself in the GROUP which have read/write permission for the device. The information regarding file permission can be found using ls -la in the /dev/input folder.
I hope it works for you. In it doesn´t work at first go, then get a cup of coffee and fight on till it works ;)
My xterm $prompt variable in my .tcshrc is:
set prompt="%{\033]0;%m:%~\007%}%{^[[;37;1m%}%B%{^[[;34;1m%}%m%{^[[;34;1m%}:%b%c%# "
The highlighted part above (%{\033]0;%m:%~\007%}) puts the hostname (%m) and the current directory (%~) in the title bar. (At least I think that that's what puts it in the title bar; it's been a while since I fiddled with this prompt).
When I run screen, however, the current directory stops getting updated when I change directories.
My questions:
How can I make this prompt work in screen?
Is there a better way to display the current directory in the title bar?
I am running linux with xterm and tcsh.
I think there is no direct way, because of the way screen works. However screen can display its own status bar, that you can define in .screenrc. Here's mine for instance :
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%=%{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
Firstly, to make it work you must check where exactly is the line with set prompt=blah-blah in your .tcshrc. For example, the code below that perfectly works in plain xterm would not work under screen in xterm:
switch ($TERM)
case "xterm*":
set prompt="%{\033]0;${HOME:t}#%m:%l:%c08\007%}%{\033[36m%}%l:%c02%#%{\033[0m%} "
# update xterm title to display current cmd in it
alias postcmd 'echo -n "\033]0;${HOME:t}#`hostname`:${tty} \!#:q\007"'
...
because screen by default sets $TERM variable to screen and not xterm! So you must add:
case "screen":
# lame, but prevents an error in screen after 'su - root'
if (! $?WINDOW) setenv WINDOW 1
set prompt="%{\033]0;${HOME:t}#%m:${WINDOW}:%c08\007%}%{\033[36m%}%c02%#%{\033[0m%} "
alias postcmd 'echo -n "\033]0;${HOME:t}#`hostname`:${WINDOW} \!#:q\007"'
...
Secondly, make sure yo have this line in ~/.screenrc:
termcapinfo xterm* 'hs:ts=\E]2;:fs=\007:ds=\E]2;\007'