-
Notifications
You must be signed in to change notification settings - Fork 20
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
Adding a new colour scheme to parse $LS_COLORS #2
Open
Nelyah
wants to merge
12
commits into
ranger:master
Choose a base branch
from
Nelyah:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
8cc5c46
Adding a new colour scheme to parse $LS_COLORS
Nelyah c0a8978
Fixing the colorscheme, which should now work.
Nelyah af9a613
Putting the code from plugin/parse_ls_colors.py in the colorscheme file.
Nelyah 7cdcbf4
Adding an exception for links not to be coloured as executable.
Nelyah e500856
Handles the case where `LS_COLORS` isn't set.
Nelyah 1975909
Removing one try/except catch inside the class
Nelyah 0480934
Added all the code to an __init__ method.
Nelyah 1ba431c
Remove print() debug
toonn a250fe8
Fixes tag and mark/cut coloring
toonn a512710
Fix many bugs and improve readability
Nelyah 3ee1526
Added comments and make bright function
Nelyah de43255
Prevent extension attributes from influencing special files
Nelyah File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
from ranger.gui.colorscheme import ColorScheme | ||
import ranger.gui.color as style | ||
import ranger.gui.context | ||
import ranger.gui.widgets.browsercolumn | ||
from os import getenv | ||
|
||
ls_colors = getenv('LS_COLORS').split(':') | ||
if ls_colors is None: | ||
ls_colors = [] | ||
ls_colors_keys = [k.split('=')[0] for k in ls_colors if k != ''] | ||
ls_colors_keys = [k.split('*.')[1] for k in ls_colors_keys if '*.' in k] | ||
|
||
# Add your key names | ||
for key in ls_colors_keys: | ||
ranger.gui.context.CONTEXT_KEYS.append(key) | ||
setattr(ranger.gui.context.Context, key, False) | ||
|
||
OLD_HOOK_BEFORE_DRAWING = ranger.gui.widgets.browsercolumn.hook_before_drawing | ||
|
||
|
||
def new_hook_before_drawing(fsobject, color_list): | ||
for key in ls_colors_keys: | ||
if fsobject.basename.endswith(key): | ||
color_list.append(key) | ||
|
||
return OLD_HOOK_BEFORE_DRAWING(fsobject, color_list) | ||
|
||
|
||
ranger.gui.widgets.browsercolumn.hook_before_drawing = new_hook_before_drawing | ||
|
||
|
||
class base(ColorScheme): | ||
progress_bar_color = 1 | ||
ls_colors = getenv('LS_COLORS').split(':') | ||
if ls_colors is None: | ||
ls_colors = [] | ||
|
||
ls_colors_keys = [k.split('=') for k in ls_colors if k != ''] | ||
tup_ls_colors = [] | ||
|
||
# Not considering file extensions | ||
# The order of these two block matters, as extensions colouring should take | ||
# precedence over file type | ||
for key in [k for k in ls_colors_keys if '.*' not in k]: | ||
if key[0] == 'fi': | ||
tup_ls_colors += [('file', key[1])] | ||
|
||
# Considering files extensions | ||
tup_ls_colors += [(k[0].split('*.')[1], k[1]) for k in ls_colors_keys | ||
if '*.' in k[0]] | ||
|
||
for key in [k for k in ls_colors_keys if '.*' not in k]: | ||
if key[0] == 'ex': | ||
tup_ls_colors += [('executable', key[1])] | ||
elif key[0] == 'pi': | ||
tup_ls_colors += [('fifo', key[1])] | ||
elif key[0] == 'ln': | ||
tup_ls_colors += [('link', key[1])] | ||
elif key[0] == 'bd' or key[0] == 'cd': | ||
tup_ls_colors += [('device', key[1])] | ||
elif key[0] == 'so': | ||
tup_ls_colors += [('socket', key[1])] | ||
elif key[0] == 'di': | ||
tup_ls_colors += [('directory', key[1])] | ||
|
||
def get_attr_from_lscolors(self, attribute_list): | ||
return_attr = 0 | ||
to_del = [] | ||
|
||
for i, attr in enumerate(attribute_list): | ||
attr = int(attr) | ||
to_del.append(i) | ||
if attr == 1: | ||
return_attr |= style.bold | ||
elif attr == 4: | ||
return_attr |= style.underline | ||
elif attr == 5: | ||
return_attr |= style.blink | ||
elif attr == 7: | ||
return_attr |= style.reverse | ||
elif attr == 8: | ||
return_attr |= style.invisible | ||
else: | ||
to_del.pop(-1) | ||
|
||
return return_attr | ||
|
||
def get_256_background_color_if_exists(self, attribute_list): | ||
colour256 = False | ||
for i, key in enumerate(attribute_list): | ||
if key == '48' and attribute_list[i + 1] == '5': | ||
colour256 = True | ||
break | ||
if colour256 and len(attribute_list) >= i + 3: | ||
return_colour = int(attribute_list[i + 2]) | ||
del attribute_list[i:i + 3] | ||
return return_colour | ||
else: | ||
return None | ||
|
||
def get_256_foreground_color_if_exists(self, attribute_list): | ||
colour256 = False | ||
for i, key in enumerate(attribute_list): | ||
if key == '38' and attribute_list[i + 1] == '5': | ||
colour256 = True | ||
break | ||
if colour256 and len(attribute_list) >= i + 3: | ||
return_colour = int(attribute_list[i + 2]) | ||
del attribute_list[i:i + 3] | ||
return return_colour | ||
else: | ||
return None | ||
|
||
def use(self, context): | ||
fg, bg, attr = style.default_colors | ||
|
||
if context.reset: | ||
return style.default_colors | ||
|
||
elif context.in_browser: | ||
if context.selected: | ||
attr = style.reverse | ||
|
||
# Values found from | ||
# http://www.bigsoft.co.uk/blog/2008/04/11/configuring-ls_colors | ||
for key, t_attributes in self.tup_ls_colors: | ||
if getattr(context, key): | ||
if key == 'executable' and (context.directory or context.link): | ||
continue | ||
t_attributes = t_attributes.split(';') | ||
colour256_fg = self.get_256_foreground_color_if_exists( | ||
t_attributes) | ||
colour256_bg = self.get_256_background_color_if_exists( | ||
t_attributes) | ||
new_attr = self.get_attr_from_lscolors(t_attributes) | ||
if new_attr is not None: | ||
attr |= new_attr | ||
|
||
# Now only the non-256 colours should be left. | ||
# Let's fetch them | ||
colour16_fg, colour16_bg = None, None | ||
for colour_val in t_attributes: | ||
colour_val = int(colour_val) | ||
# This is an attribute | ||
if (colour_val >= 30 | ||
and colour_val <= 37): # Basic colours | ||
colour16_fg = colour_val - 30 | ||
# eight more basic colours | ||
elif (colour_val >= 90 and colour_val <= 97): | ||
colour16_fg = colour_val - 82 | ||
|
||
elif (colour_val >= 40 and colour_val <= 47): | ||
colour16_bg = colour_val | ||
# eight more basic colours | ||
elif (colour_val >= 90 and colour_val <= 97): | ||
colour16_bg = colour_val | ||
|
||
if colour256_fg is not None: | ||
fg = colour256_fg | ||
elif colour16_fg is not None: | ||
fg = colour16_fg | ||
|
||
if colour256_bg is not None: | ||
bg = colour256_bg | ||
elif colour16_bg is not None: | ||
bg = colour16_bg | ||
|
||
return fg, bg, attr |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when I unset LS_COLORS this throws an exception that's uncaught. (
getenv('LS_COLORS')
is None, sogetenv('LS_COLORS').split(':')
raises an AttributeError.)I think you want to check if
getenv('LS_COLORS')
isNone
instead ofls_colors
. Or catch the exception.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you provide a default to
getenv
? Otherwise you can useos.environ.get('LS_COLORS', default value)
. Imo that looks like the proper way to solve this problem.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to look it up myself,
getenv('LS_COLORS', default='')
looks good. (NB: in two places in the file)What I didn't realise earlier. It seems the uncaught exception makes ranger fall back to the default colors. Once I add the
default
value or exception handling inclass base(ColorScheme):
and whenLS_COLORS
is not set, then ranger becomes black&white.I don't think this is what we want here (
ls --color
falls back to default colors whenLS_COLORS
is not set).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, if we want the default
LS_COLORS
, we should either letranger
automatically fall back to its default scheme, or we should manually read the defaultdircolors
file or run thedircolors
command without arguments to get the default colouring. Also, are we sure that is whatranger
really does? (falling back to defaultLS_COLORS
) This could simply be a matter of catching the exception.I've had trouble however finding the system wide config file that
dircolors
automatically reads. The man page (man dir_colors
) points to either~/.dircolors
(user-defined) or/etc/DIR_COLORS
(system-wide). I, however, do not have the system-wide one and yetdircolors
is still able to read the colours from somewhere.Have you had any luck finding whence it gets the colours?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what's the best to do. I guess given the name 'ls_colors' it should be as close as reasonable to "what ls does".
ranger gets its default colors from https://github.com/ranger/ranger/blob/master/ranger/colorschemes/default.py which happens to be the same as (my?) ls defaults when LS_COLORS is unset.
I also don't see where my
dircolors
gets its defaults from.Given we don't seem to see where
dircolors
gets its config from (and one would need to check user file, system file, fallback) I think callingdircolors
ifLS_COLORS
is unset is a good handling.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a commit to handle the case where
LS_COLORS
isn't set.Scenario cases:
LS_COLORS
is defined and parsedLS_COLORS
isn't defined,dircolors
is called and we use its output to define theLS_COLORS
for the colorschemeLS_COLORS
isn't defined and thedircolors
command can't be found. We use a black & white colorscheme.the 3) is probably not what the user want, but it might be a good idea to let them know something is wrong if neither a
LS_COLORS
env variable or adircolors
command can be found while using thels_colors.py
scheme.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranger probably "falls back", actually doesn't change to ls_colors.py, because that throws an error.
The proper behavior would be to do what ls does. The
default.py
colorscheme doesn't completely match whatls --color
does withoutLS_COLORS
set.I meant to use whatever actually is the default value for
LS_COLORS
as the default but calling dircolors every time is probably fine too.Do you really need to duplicate the try/except block for the getenv?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@toonn
Can you elaborate? I don't see duplication here. Or should this thread be resolved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This refers to an old version. the old file I still have from September has two calls
getenv('LS_COLORS')
. The current version in this PR does not have that duplication.