Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Tmux Selector #1897

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open

Added Tmux Selector #1897

wants to merge 10 commits into from

Conversation

StopMotionCuber
Copy link
Contributor

@StopMotionCuber StopMotionCuber commented Mar 23, 2018

Implementation will show segments depending on whether the current active tmux client is connected via SSH
This still has the flaw that it does not draw independent status bars to the screens, but draws the same depending on the status of the last active pane (whether that has is connected via SSH)
References #1895 and #858

Implementation will show segments depending on whether the current active tmux client is connected via SSH
This still has the flaw, that it does not draw independent the screen, but draw the same depending on the status of the last active pane
References #1895 and #858
def tmux_via_ssh(pl, segment_info, mode, caching=True, default=False):
'''Returns True if tmux client is connected via SSH
'''
pid = get_tmux_output(pl, "display", "-p", "#{client_pid}")
Copy link
Contributor

@ZyX-I ZyX-I Mar 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not passing environment anywhere, this is not going to work right. The whole bindings file itself was never intended to work in daemon though, so currently you can’t pass environment there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way of doing it?
For me this worked okay-ish (it got the display -p #{client_pid} output for the current active tmux window so that it would not show excluded segments when I was connected via SSH to the machine and working actively on it), also when using the powerline-daemon

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need another tmux instance not run from ssh for that to not be OK. This does not mean that variant is acceptable, you would need to refactor relevant code.

if pid in _cached_clients:
return _cached_clients[pid]
try:
pstree_out = subprocess.check_output(("pstree", "-s", pid)).decode()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use subprocess directly, and do not use check_output at all as it is not present in all supported Python versions. There is run_cmd in powerline.lib.shell for this purpose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually don’t use pstree, as well as any regular expressions. psutil.Process class provides everything needed, it works in-process, it should be more portable and it would not query all the parents, just up to the one that happens to match sshd. Just need to mention requirements in the documentation. pstree is the requirement as well though.

_cached_clients = {}
# This Regex parses pstree -s <Process_ID> information
# It will match, if any process name is sshd
SSHD_REGEX = re.compile(r"(?:^|\W)sshd(?:^|\W)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the strings in powerline use single quotes.

SSHD_REGEX = re.compile(r"(?:^|\W)sshd(?:^|\W)")


def tmux_via_ssh(pl, segment_info, mode, caching=True, default=False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selectors do not take additional arguments, so they must not be present. This will only be confusing in documentation.

if not pid.isnumeric():
return default
if caching:
if pid in _cached_clients:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logical to write using EAFP principle: just return _cached_clients[pid] and if that throws KeyError proceed with using psutil.

@StopMotionCuber
Copy link
Contributor Author

I have done changes so that it works now consistently.
I yet have to add backwards compatibility for tmux < 1.7 and add documentation (including psutil requirement).
For my machine this is working in a nice way. Tell me if you have any concerns about this code

@StopMotionCuber
Copy link
Contributor Author

I added documentation now for the tmux SSH selector.
This works like a charm for my tmux version and it should work for every tmux-version >= 2.1.
@ZyX-I I would really appreciate if you could review these changes.

@@ -107,6 +107,10 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
'-w', '--width', type=int,
help='Maximum prompt with. Triggers truncation of some segments.'
)
parser.add_argument(
'--process-id', metavar='PID', type=int,
help='process_ID for the desired process'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation should start with a capital, end with dot, not use identifiers where they are not meant to (what’s wrong with “Process ID”?) and be more descriptive then “desired process”. I have no idea what “desired process” is supposed to mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would 'The process ID of process that renders powerline.' be okay for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine.


Requires the ``psutil`` module.

Works only for tmux versions >= 2.1'''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tied to --process-id being supplied on command-line, not to tmux version in any fashion. Also closing ''' needs to be on its own line and it is not qualified to be a sentence end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#{client_pid} got introduced with tmux 2.1, so it is not supported before

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tmux bindings implementation detail. All what selector cares about is whether --process-id is supplied or not, if it is it would be completely happy without even having tmux installed.

@@ -0,0 +1,34 @@
# vim:fileencoding=utf-8:noet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I would actually suggest moving that to powerline/selectors/proc.py and get rid of any references to tmux here. Neither idea of the process tree traversal nor current implementation of the selector is really tmux-specific.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is good, however this requires the exclude function to be named powerline.selectors.proc.is_ssh.
I would propose to change this into a file named common.py and add this module to the general search path for the selectors

@@ -0,0 +1,34 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.bindings.tmux import get_tmux_output
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import.

from powerline.bindings.tmux import get_tmux_output


_cached_clients = {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keys are process identifiers.


_cached_clients = {}

def tmux_via_ssh(pl, segment_info, mode):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in_ssh.

_cached_clients = {}

def tmux_via_ssh(pl, segment_info, mode):
'''Returns True if tmux client is connected via SSH
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

… if ``--process-id`` has sshd as its ancestor

try:
import psutil
except ImportError:
pl.warn('Module "psutil" is not installed, thus we cannot detect whether tmux is run via ssh')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check should be performed at module start. See cpu_load_percent segment in powerline/segments/common/sys: depending on whether import is successfull it either creates an actual class or a dummy which does nothing, but a warning with None return.

return False
process_id = segment_info['args'].process_id
if process_id is None:
pl.warn("Process ID was not passed, maybe you are using tmux version < 2.1")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove “, maybe …”.

@StopMotionCuber
Copy link
Contributor Author

Thanks for your Feedback @ZyX-I.
I changed my code according to your requests and did some refactoring to have a common selector module.

@ZyX-I
Copy link
Contributor

ZyX-I commented Apr 24, 2018

Do not add second default selectors module. There must not be two default modules out there. Also if you were to do that you also need to

  • Add tests for new behaviour.
  • Change linter.
  • Change documentation.

@StopMotionCuber
Copy link
Contributor Author

The problem with the current approach is that the default module is depending on your current powerline renderer.
For that and my usecase I would have to add it back to tmux.py which would be not portable for other renderers (or they had to add powerline.selectors.tmux.is_ssh in their config. This is too confusing as tmux is not even used).
The other approach would be to always be explicit with powerline.selectors.common.is_ssh as include/exclude_function. I do think this is intuitive for a configuration file either.
If you have a suggestion for a better approach then hit me up, otherwise I will have a look at further needed changes.

@ZyX-I
Copy link
Contributor

ZyX-I commented Apr 24, 2018

This is not the first place where path to function is (or needs to be) full with module, and it will not be the last. But AFAIR there are exactly no places where there are two default modules. I would (now) happily remove all default modules completely everywhere, this makes functions easier to discover when needed and configuration file is not a thing that is edited too frequently to bother, but this is backwards incompatible and also not all people share same opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants