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

file_status: allow several paths, new format #1369

Merged
merged 21 commits into from
Jul 5, 2018
Merged
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 110 additions & 38 deletions py3status/modules/file_status.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,50 @@
# -*- coding: utf-8 -*-
"""
Display if a file or directory exists.
Display if files or directories exists.

Configuration parameters:
cache_timeout: how often to run the check (default 10)
format: format of the output. (default '{icon}')
icon_available: icon to display when available (default '●')
icon_unavailable: icon to display when unavailable (default '■')
path: the path to a file or dir to check if it exists (default None)

Color options:
color_bad: Error or file/directory does not exist
color_good: File or directory exists
cache_timeout: refresh interval for this module (default 10)
format: display format for this module
(default '\?color=paths [\?if=paths ●|■]')
Copy link
Contributor

Choose a reason for hiding this comment

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

If I remember it correctly, the family mentioned something about storing icons properly, eg (default '\?color=paths [\?if=paths \u25cf|\u25a0]') so I assume we should change it everywhere to be similar to SAMPLE OUTPUT.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What is the goal? For readability? Compliance?

Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

I don't remember all the details. I think readability so some things are not rendered as blocks or to avoid cause minor confusion. It may or may not had to do more with control characters. ~~EDIT: Maybe wait for the family.~~~

FILE_SEPARATOR = u' '
GROUP_SEPARATOR = u' '
RECORD_SEPARATOR = u' ' 
UNIT_SEPARATOR = u' '

versus more explicit...

FILE_SEPARATOR = u'\u231a'
GROUP_SEPARATOR = u'\u231d'
RECORD_SEPARATOR = u'\u231e' 
UNIT_SEPARATOR = u'\u231f'

format_path: format for paths (default '{basename}')
format_path_separator: show separator if more than one (default ' ')
path: specify a string or a list of paths to check (default None)
thresholds: specify color thresholds to use
(default [(0, 'bad'), (1, 'good')])

Format placeholders:
{icon} icon for the current availability
{format_path} format for paths
{paths} number of paths, eg 1, 2, 3

@author obb, Moritz Lüdecke
format_path path placeholders:
Copy link
Contributor

Choose a reason for hiding this comment

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

format_path path placeholders:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nitpick :)

{basename} basename of pathname
{pathname} pathname

Color options:
color_bad: files or directories does not exist
color_good: files or directories exists

Color thresholds:
format:
paths: print a color based on the number of paths

Examples:
```
# add multiple paths with wildcard or with pathnames
file_status {
path = ['/tmp/test*', '~user/test1', '~/Videos/*.mp4']
}

# colorize basenames
file_status {
path = ['~/.config/i3/modules/*.py']
format = '{format_path}'
format_path = '\?color=good {basename}'
format_path_separator = ', '
}
```

@author obb, Moritz Lüdecke, Cyril Levis (@cyrinux)

SAMPLE OUTPUT
{'color': '#00FF00', 'full_text': u'\u25cf'}
Expand All @@ -25,20 +53,23 @@
{'color': '#FF0000', 'full_text': u'\u25a0'}
"""

from os.path import expanduser, exists
from glob import glob
from os.path import basename, expanduser

ERR_NO_PATH = 'no path given'
STRING_NO_PATH = 'no path given'
Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

missing path for more consistency with other modules.. and feels more family friendly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nitpick :)

DEFAULT_FORMAT = u'\?color=paths [\?if=paths ●|■]'


class Py3status:
"""
"""
# available configuration parameters
cache_timeout = 10
format = '{icon}'
icon_available = u''
icon_unavailable = u''
format = DEFAULT_FORMAT
format_path = u'{basename}'
format_path_separator = u' '
path = None
thresholds = [(0, 'bad'), (1, 'good')]

class Meta:
deprecated = {
Expand All @@ -57,32 +88,73 @@ class Meta:
}

def post_config_hook(self):
if self.path:
self.path = expanduser(self.path)
if not self.path:
raise Exception(STRING_NO_PATH)

# deprecation
on = getattr(self, 'icon_available', None)
off = getattr(self, 'icon_unavailable', None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Not same from diff I gave you. {icon} display None instead of \u... here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oups. 😜

if self.format == DEFAULT_FORMAT and (on or off):
self.format = u'\?if=paths {}|{}'.format(on or u'●', off or u'■')
new_format = u'\?color=paths [\?if=paths {}|{}]'
Copy link
Contributor

Choose a reason for hiding this comment

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

We forget to replace {icon} with new_format. See if you can fix this.

Copy link
Contributor Author

@cyrinux cyrinux Jun 20, 2018

Choose a reason for hiding this comment

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

Not sure to understand, we don't need {icon} in new format no? And if I use legacy style I see my icon_available or icon_unavailable and I have deprecation log.

Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

That removes the icon_* okay... and for default format only, but not the old existing format. We need to keep the old format alive too... eg format = 'VPN {icon}' shouldn't break.

self.format = new_format.format(on or u'●', off or u'■')
msg = 'DEPRECATION: you are using old style configuration '
msg += 'parameters you should update to use the new format.'
self.py3.log(msg)

# convert str to list + expand path
if not isinstance(self.path, list):
self.path = [self.path]
self.path = list(map(expanduser, self.path))

self.init = {'format_path': []}
if self.py3.format_contains(self.format, 'format_path'):
self.init['format_path'] = self.py3.get_placeholders_list(
self.format_path
)

Copy link
Contributor

Choose a reason for hiding this comment

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

Keep this so we can do expanduser(path) once instead of every refresh interval.

Copy link
Contributor Author

@cyrinux cyrinux Jun 12, 2018

Choose a reason for hiding this comment

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

I had a doubt about this, refresh is for example when I py3-cmd resfresh file_status? I thought this part was only excecuted at the py3status start/restart.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not understand this sorry, could you rephrase? "I'd clear this with the fam first."

Copy link
Contributor

Choose a reason for hiding this comment

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

Have a discussion with tobes and/or ultrabug. They our fam.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh sorry, fam = familly >_>

def file_status(self):
if self.path is None:
return {
'color': self.py3.COLOR_ERROR or self.py3.COLOR_BAD,
'full_text': ERR_NO_PATH,
'cached_until': self.py3.CACHE_FOREVER,
}

if exists(self.path):
icon = self.icon_available
color = self.py3.COLOR_GOOD
else:
icon = self.icon_unavailable
color = self.py3.COLOR_BAD
Copy link
Contributor

Choose a reason for hiding this comment

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

There sure are lot of changes. We might as well see this all the way to finish... by removing colors, make and default thresholds with 0, 1. With glob and several paths implemented, we might want thresholds anyway as it would enhance this module... allowing us to print colors based on number of paths somewhere.

This module is useful now because I can use this to print names of custom modules... and globbing. Thank you for working on this. :-)


response = {
# init datas
paths = sorted([files for path in self.path for files in glob(path)])
Copy link
Contributor

Choose a reason for hiding this comment

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

Because of this, we don't need paths = list(map(glob, self.path)) anymore.

count_path = len(paths)
format_path = None

# format paths
if self.init['format_path']:
new_data = []
format_path_separator = self.py3.safe_format(
self.format_path_separator
)

for pathname in paths:
path = {}
for key in self.init['format_path']:
if key == 'basename':
value = basename(pathname)
elif key == 'pathname':
value = pathname
else:
continue
path[key] = self.py3.safe_format(value)
new_data.append(self.py3.safe_format(self.format_path, path))

format_path = self.py3.composite_join(
format_path_separator, new_data
)

if self.thresholds:
self.py3.threshold_get_color(count_path, 'paths')

return {
'cached_until': self.py3.time_in(self.cache_timeout),
Copy link
Contributor

Choose a reason for hiding this comment

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

cache_timeout = -1 in your example means once. You may want cache_timeout = 0 instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my example I use py3-cmd refresh file_status for try ;)

'full_text': self.py3.safe_format(self.format, {'icon': icon}),
'color': color
'full_text': self.py3.safe_format(
self.format, {
'paths': count_path,
'format_path': format_path
}
)
}

return response


if __name__ == "__main__":
"""
Expand Down