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

Enable to change the background color of dialogs. #413

Conversation

pocari
Copy link
Contributor

@pocari pocari commented Dec 29, 2021

Reline in its current state also has the ability to change the background color using the bg_color attribute of DialogRenderInfo, but I couldn't seem to use that feature right now.

I changed it so that in addition to the bg_color, the background color of the item being selected for completion can also be set, and then it can be defined in "inputrc" so that the user can choose the color.

default color:
スクリーンショット 2021-12-29 17 12 37

customize sample:
スクリーンショット 2021-12-29 17 13 54

You can try with the following settings

% cat Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

gem 'reline',  github: 'pocari/reline', branch: 'support-for-changing-the-background-color-of-dialogs'
gem 'irb',  github: 'pocari/irb', branch: 'feature/add-config-params-for-reline'

% bundle install
% cat ~/.irbrc

IRB.conf[:DIALOG_DEFAULT_BG_COLOR] = 40
IRB.conf[:DIALOG_POINTER_BG_COLOR] = 47

% bundle exec irb

@pocari pocari changed the title Make it possible to set the background color of the dialog and the ba… Enable to change the background color of dialogs. Dec 29, 2021
@elfham
Copy link
Contributor

elfham commented Jan 9, 2022

Readline complains about new unknown keywords in inputrc.

% echo "set dialog-default-bg-color 40" >> ~/.inputrc
% echo "set dialog-pointer-bg-color 47" >> ~/.inputrc
% bash
readline: ~/.inputrc: line 14: dialog-default-bg-color: unknown variable name
readline: ~/.inputrc: line 15: dialog-pointer-bg-color: unknown variable name
$ 

@pocari
Copy link
Contributor Author

pocari commented Jan 10, 2022

@elfham If Reline is mandatory to be compatible with readline, my implementation this time may not be good.
But we can't customize the background color if we can't pass some value to the reline. If you have a better idea for this, please let me know.

@elfham
Copy link
Contributor

elfham commented Jan 10, 2022

Since inputrc is a common configuration file for Readline and Reline, I'm afraid that apps that use Readline will suffer the side effects of adding this keyword.

I'm not an expert on Reline, so I don't know if this is the right way to do it, but how about setting it up in irbrc?

@pocari
Copy link
Contributor Author

pocari commented Jan 10, 2022

@elfham I did not know that irbrc existed. I'll try to see if I can use it. Thank you.

@pocari
Copy link
Contributor Author

pocari commented Jan 17, 2022

@elfham I modified irbrc so that it can pass configuration items. (ruby/irb#337)

You can try this fix with a Gemfile like the one below.

% cat Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

gem 'reline',  github: 'pocari/reline', branch: 'support-for-changing-the-background-color-of-dialogs'
gem 'irb',  github: 'pocari/irb', branch: 'feature/add-config-params-for-reline'

% bundle install
% cat ~/.irbrc

IRB.conf[:DIALOG_DEFAULT_BG_COLOR] = 40
IRB.conf[:DIALOG_POINTER_BG_COLOR] = 47

% bundle exec irb

スクリーンショット 2022-01-17 23 00 08

@elfham
Copy link
Contributor

elfham commented Jan 18, 2022

I have tried this fix and it seems to be working well.
Thanks for the fix.

@joeyparis
Copy link

@pocari also confirmed working with no problems

@pocari
Copy link
Contributor Author

pocari commented Feb 14, 2022

I have also made the foreground color changeable.
ruby/irb#337 (comment)

@sshock
Copy link
Contributor

sshock commented Mar 5, 2022

Would love to see this feature! Is there any reason it hasn't been approved and merged yet?

@elfham
Copy link
Contributor

elfham commented Mar 6, 2022

I too see no problem with this feature.

BTW, the main developer, @aycabta, does not seem to be very active since the end of last year.
He tweeted that he suffered a mild stroke and I am concerned ......

if i == pointer
bg_color = '45'
if dialog_render_info.pointer_fg_color
Copy link
Member

@st0012 st0012 May 16, 2022

Choose a reason for hiding this comment

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

How about setting the default values when initializing the reline like other configs?

reline/lib/reline.rb

Lines 546 to 551 in 5b3fc02

core.basic_word_break_characters = " \t\n`><=;|&{("
core.completer_word_break_characters = " \t\n`><=;|&{("
core.basic_quote_characters = '"\''
core.completer_quote_characters = '"\''
core.filename_quote_characters = ""
core.special_prefixes = ""

Then we don't need these if statements because the dialog_render_info should always have values from the config default. It will also help users getting the default by just calling Reline.dialog_default_fg_color.

If we really worry about the values being nil by accident, we should validate them at the setter.

@pocari
Copy link
Contributor Author

pocari commented May 22, 2022

@st0012 Thanks for the comments. Those points seemed right to me. However, the properties I added this time were defined in the below section, so I wasn't sure if I should treat them the same way.

DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)

@st0012
Copy link
Member

st0012 commented May 23, 2022

Since we want them to be exposed externally, I think it doesn't matter where they'll be used. The point is to make the values more easily accessible.

@pocari
Copy link
Contributor Author

pocari commented May 28, 2022

@st0012 Thank you. I have added the code as you mentioned. 9bf4979

lib/reline.rb Outdated
@@ -610,6 +610,10 @@ def self.core
core.filename_quote_characters = ""
core.special_prefixes = ""
core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
core.dialog_default_bg_color = 46 # Cyan
core.dialog_default_fg_color = 37 # White
core.dialog_pointer_bg_color = 45 # Maggenta
Copy link
Contributor

Choose a reason for hiding this comment

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

Maggenta => Magenta

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Maumagnaguagno Thanks. I have fixed it.

@st0012
Copy link
Member

st0012 commented May 29, 2022

@pocari Thanks for the update. It looks good to me 👍
Do you think you can update the description example to a version that doesn't require the irb patch? I think directly setting reline's color with the exposed APIs should work too? Something like:

# .irbrc
Reline.dialog_default_bg_color = 40
Reline.dialog_pointer_bg_color = 47

@hsbt Would you mind giving this a look? I know @aycabta is the maintainer but he seems to have been away for a while.

I think being able to change the background color of the dialog is essential for good user-experience. And as shown in ruby/irb#328, the default color doesn't look good with some themes (for example, mine). And many users decided to turn off the autocomplete feature altogether because of the color.

Of course, to completely fix the irb's issue will require some more work (releasing this change in a minor release + bump irb's dependency requirement + cut another irb minor release). But having this merged will already allow some users to workaround the issue themselves.

@pocari
Copy link
Contributor Author

pocari commented May 30, 2022

@st0012 As for irbrc, I was advised by another person and made the following changes.
ruby/irb#337 (comment)

Do you think you can update the description example to a version that doesn't require the irb patch?

That may be possible.

@pocari
Copy link
Contributor Author

pocari commented May 30, 2022

@st0012 As you said it was possible. Thanks! You can try it with the following

% cat Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

gem 'reline',  github: 'pocari/reline', branch: 'support-for-changing-the-background-color-of-dialogs'

% bundle install
% cat ~/.irbrc
if Reline
  Reline.dialog_default_bg_color = 40
  Reline.dialog_pointer_bg_color = 47
  Reline.dialog_pointer_fg_color = 30
  Reline.dialog_pointer_bg_color = 45
end

% bundle exec irb

I have added a condition because there must be some environments where Reline is not installed.

@st0012
Copy link
Member

st0012 commented May 30, 2022

@pocari To be clear, I know the irb change is necessary. But having reline-only example will make this change easier to understand and test 🙂

@st0012
Copy link
Member

st0012 commented Jun 13, 2022

@pocari Can you rebase your branch to see if the CI passes?

pocari and others added 3 commits June 25, 2022 23:56
Co-authored-by: Peter Zhu <[email protected]>
…f github.com:pocari/reline into support-for-changing-the-background-color-of-dialogs
@pocari pocari force-pushed the support-for-changing-the-background-color-of-dialogs branch from d0559f8 to 2302293 Compare June 26, 2022 05:56
Copy link
Member

@peterzhu2118 peterzhu2118 left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution!

@st0012
Copy link
Member

st0012 commented Jun 27, 2022

@hsbt @peterzhu2118 Do you think we can cut a 0.4.0 release for this change? Here are the changes since v0.3.1

There are a few reasons:

  1. We can test these new APIs early.
  2. irb can start requiring reline >= 0.4.0, which can make the implementation cleaner and also make users adopting it easier.
    • Instead of installing both irb and reline on GH source, the user will only need to install the latest irb.

Or do you have any concerns/thoughts?

@nobu
Copy link
Member

nobu commented Jun 27, 2022

46, 37 and so on are not “colors”, but attributes including where they are applied to, foreground or background.
That means you can set “background” to a foreground attribute 37, for instance.
So I think “attribute” string would be more proper here.

@pocari
Copy link
Contributor Author

pocari commented Jun 28, 2022

@nobu
Just to confirm, are you saying that dialog_default_bg_attribute is better than dialog_default_bg_color, for example?

@st0012
Copy link
Member

st0012 commented Jun 28, 2022

I feel "color" is still a better name because that's what we want them to be used for.
But the APIs can indeed do more to prevent misuse.

How about this

Reline.dialog_default_bg_color = :black
Reline.dialog_pointer_bg_color = :white
Reline.dialog_pointer_fg_color = :black
Reline.dialog_pointer_bg_color = :white

And the color assignment logic can do:

# lib/reline/config.rb
def dialog_default_bg_color=(color)
  @dialog_default_bg_color = select_color_code(:bg, color)
end

def select_color_code(type, color)
  if :bg
    case color
    when :black
      40
    when :white
      47
      # ...... the rest
    else
      raise ColorNotFound
    end
  else
    case color
    when :black
      30
    when :white
      37
      # ...... the rest
    else
      raise ColorNotFound
    end
  end
end

@nobu
Copy link
Member

nobu commented Jun 28, 2022

To set colors only, dialog_default_bg_color etc make sense, and passing color names would be better.
However attributes are not only colors, but highlight, reverse video, underline, etc too.

Another concern is "\e[#{bg_color}m\e[#{fg_color}m#{str}" will reset bg_color if fg_color is set to 0.
The setters don't check the arguments.

BTW, your select_color_code can be:

def select_color_code(type, color)
  case type
  when :bg; 40
  when :fg; 30
  else raise ColorNotFound
  end +
  case color
  when :black; 30
  when :white; 37
    # ...... the rest
  else raise ColorNotFound
end

or even Hash#fetch may be useful.

@st0012
Copy link
Member

st0012 commented Jun 28, 2022

However attributes are not only colors, but highlight, reverse video, underline, etc too.

That's true. But from what I've seen so far, the only request is on color and not other text effects. I'm sure some users would want that but perhaps we can design better APIs for those cases when we get more feedback?

Another concern is "\e[#{bg_color}m\e[#{fg_color}m#{str}" will reset bg_color if fg_color is set to 0.

The reason I want to pass color symbol instead of integer is to prevent cases like this, as we won't have 0 available in the case statement.

BTW, your select_color_code can be:

That's a great suggestion 👍 I'll open a PR shortly.

@james-caresnap
Copy link

46, 37 and so on are not “colors”, but attributes including where they are applied to, foreground or background.
That means you can set “background” to a foreground attribute 37, for instance.
So I think “attribute” string would be more proper here.

The linux man page calls them "color sequences".

However, the ANSI escape code standard calls them "control sequences".

st0012 added a commit to st0012/reline that referenced this pull request Jun 28, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_code APIs to access the raw code.
@st0012 st0012 mentioned this pull request Jun 28, 2022
st0012 added a commit to st0012/reline that referenced this pull request Jun 28, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.
st0012 added a commit to st0012/reline that referenced this pull request Jun 28, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.
@nobu nobu added the enhancement New feature or request label Jun 29, 2022
end
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
@output.write "\e[#{bg_color}m#{str}"
@output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
Copy link
Member

Choose a reason for hiding this comment

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

This can be "\e[#{bg_color};#{fg_color}m#{str}".

end
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
@output.write "\e[#{bg_color}m#{str}"
@output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
@output.write "\e[37m"
Copy link
Member

Choose a reason for hiding this comment

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

Maybe scrollbar color too?

st0012 added a commit to st0012/reline that referenced this pull request Jun 30, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.
st0012 added a commit to st0012/reline that referenced this pull request Jul 11, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.
st0012 added a commit to st0012/reline that referenced this pull request Jul 11, 2022
As pointed out in the
[comment](ruby#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.
matzbot pushed a commit to ruby/ruby that referenced this pull request Jul 15, 2022
…r APIs

As pointed out in the
[comment](ruby/reline#413 (comment)),
the code is actually a control sequence and not only for colors.

To make the dialog color APIs safer to use, we should restrict its
usages and extract away the bg/fg concept from the input.

So in this commit, I made these changes:

1. The dialog_*_bg/fg_color APIs only takes and returns color names (symbol):
  - :black
  - :red
  - :green
  - :yellow
  - :blue
  - :magenta
  - :cyan
  - :white
2. Add additional dialog_*_bg/fg_color_sequence APIs to access the raw code.

ruby/reline@b32a977766
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

Successfully merging this pull request may close these issues.

10 participants