dark theme

1,096 views
Skip to first unread message

Asif Ali Rizvan

unread,
Apr 25, 2023, 11:07:03 AM4/25/23
to scite-i...@googlegroups.com
Hi,
I'm the scite maintainer at flathub.  https://flathub.org/apps/org.scintilla.SciTE

I'd like to request a dark theme for scite, as dark themes are very popular these days due to comfort on eyes. white background is very uncomfortable for the eyes with scite.

Could you please consider a "Dark/Light" Theme in the Options menu or in the View menu in SciTE?

Regards,
Rizvan.

Red M

unread,
Apr 25, 2023, 12:06:04 PM4/25/23
to scite-i...@googlegroups.com
It already supports a dark mode, however this is set by the DE, which you won't have in a flatpack, so SciTE defaults to the default GNOME theme.
image.png

--
You received this message because you are subscribed to the Google Groups "scite-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scite-interes...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scite-interest/CAPsk_WnL5iJ2wBQtrzQgeOapcXuPCYK5PgZTCyPXmirm%2Bv%3DChA%40mail.gmail.com.

Neil Hodgson

unread,
Apr 25, 2023, 6:51:04 PM4/25/23
to scite-i...@googlegroups.com
Asif Ali Rizvan:

> I'd like to request a dark theme for scite, as dark themes are very popular these days due to comfort on eyes. white background is very uncomfortable for the eyes with scite.

Red M has covered SciTE's handling of global themes for GTK widgets but that doesn't cover theming the text editing area where syntax styling is applied to produce visual styles. SciTE provides basic support for preferences reacting to the system's dark mode with a $(Appearance) property.

SciTE does not support theming in a way that is similar to most editors. Each individual lexical class specifies style attributes and there is no lookup into a theme definition. Therefore, it is not currently possible to create a dark theme for SciTE. I have no plans to work on this.

Neil

Asif Ali Rizvan

unread,
Apr 25, 2023, 9:51:04 PM4/25/23
to scite-i...@googlegroups.com
Hi Red_M,

I was talking about the editor theme, The window is black, but the editor white background is glaring. Yes, we can use "user options file" to set colors, but that is stone age behavior. And it's burdensome for the user. 

Because of this white background (light theme colors) I myself am not using scite as my go to text editor, because it hurts my eyes to look at white backgrounds. Ironically I am the packager for flathub.
image.png
Regards,
Rizvan.


Red M

unread,
Apr 25, 2023, 10:18:14 PM4/25/23
to scite-i...@googlegroups.com
Yes, I'm pretty sure that has also been the intended behaviour since day dot to use config files to manage user settings.
This is why I have my own dot files as a git repository to make carrying my own settings from one machine to another as easy as possible.
As an avid user of the editor, I prefer it this way because I can do things like make a theme manager for SciTE. This kind of configuration system is beautifully simple and effective.

Red M

unread,
Apr 26, 2023, 1:54:49 AM4/26/23
to scite-interest
For some reason this didn't come through to my mailbox so google groups might be being weird again.
I do have such a lookup working in my own configs (in my dotfiles) but it does require a bit of work to get it going as I had to implant luarocks into scite but it all works out of a normally compiled SciTE via the Lua startup script interface.

Asif Ali Rizvan

unread,
Apr 27, 2023, 2:45:54 AM4/27/23
to scite-i...@googlegroups.com
> SciTE does not support theming in a way that is similar to most editors. Each individual lexical class specifies style attributes and there is no lookup into a theme definition. Therefore, it is not currently possible to create a dark theme for SciTE. I have no plans to work on this.

>Neil

Ok, I understand creating themes is time consuming and not fun. Could we at least have an inverted colors like feature for the edit area? I hope inverting the colors esp. of the background is not a trouble?



Here's the default light gtk style and white backgound and theme:
image.png


Here's the same window with inverted colors,  using gnome extension https://extensions.gnome.org/extension/5829/true-color-invert/ we can see the text looks good. The extension only changes the black and grey colors to white and lightens the dark colors a bit, it is a GNOME shell extension for inverting window colors in a hue preserving manner. https://github.com/Lynet101/gnome-true-color-invert

With Light GTK style + Inverted:

image.png

with Dark GTK style (system wide) + Inverted:

image.png


This is what I'd like to see the edit area inverted + dark style:
Dark Style + Inverted Colors (edited with gimp) used extension https://github.com/Lynet101/gnome-true-color-invert:


image.png

This is what I got just by changing these, the colors are little darker (inverted color extension makes it a bit lighter I presume):
.SciTEUser.properties
style.*.32=$(font.base),back:#101010,fore:#BBBBBB
fold.margin.colour=#505050
fold.margin.highlight.colour=#101010


image.png

Please consider.

Regards,
Rizvan.


--
You received this message because you are subscribed to the Google Groups "scite-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scite-interes...@googlegroups.com.

Neil Hodgson

unread,
Apr 27, 2023, 7:08:02 PM4/27/23
to scite-interest
Asif Ali Rizvan:

> Could we at least have an inverted colors like feature for the edit area?

Inverted colours are generally disliked.

> Here's the same window with inverted colors,

Those colours are not inverted: magenta is used for "<stdio.h>" in both. The inverse of magenta is green.

The example is inverting the light (or brightness) value of the colours.

> Please consider.

If someone wants to contribute a good implementation of a brightness inversion option it can be included.

Neil

andrew strain

unread,
May 2, 2023, 3:40:16 PM5/2/23
to scite-interest
In the past I patched `static Colour ColourFromString()` in SciTEProps to do this, it worked well for me although some colours defined in Scites source may never go by ColourFromString. It may be preferable to patch `inline constexpr Scintilla::Colour ColourRGB(` and `inline constexpr Scintilla::Colour ColourRGB(` in StyleDefinition.h

The simplest luminosity inversion I tested goes :
``
  int inv_red   =  0xff - ( green + blue ) / 2;
  int inv_green =  0xff - ( red   + blue ) / 2;
  int inv_blue  =  0xff - ( red   + green) / 2;       // ( divide by 2 or '>>1' )
``

I find it works nicely while being so short, a 'flaw' is that the result is less saturated than the original, however less saturation might even be aesthetic when lit on a dark background.

A more obscure formula can do a similar inversion with a bit of saturation reboost:
``
  int i_red  =  0xff + ( 2*red - 7*grn - 7*blu ) / 12;
  int i_grn  =  0xff + ( 2*grn - 7*red - 7*blu ) / 12;
  int i_blu  =  0xff + ( 2*blu - 7*grn - 7*red ) / 12;
 
  i_red = math.min( 255 , math.max(0 , i_red ) );
  i_grn = math.min( 255 , math.max(0 , i_grn ) );
  i_blu = math.min( 255 , math.max(0 , i_blu ) );
``

I wrote these years ago, anyone is welcome to use them. I would send a patch myself I am just not
confident where to place them in the source.

I currently use a much larger conversion function, which partially adjusts for relative brightness between r,g,b values and throws in other transformations. It is done in a lua script which rewrites a section of user.properties where symbolic colour names are defined which the rest of the property scripts use instead of rgb, and it stores history and presets.

But I think either of those simple conversions should work nicely for a light to dark theme switch.

Baltasar García Perez-Schofield

unread,
May 3, 2023, 6:21:56 AM5/3/23
to scite-i...@googlegroups.com

Hi,


Personally, I find the way SciTE configures its colors too complex. I mean, you depend on the lexer in order to set colors for keywords, identifiers, numbers... At the top level, I guess SciTE knows nearly nothing about symbols, i.e., the mentioned keywords and identifiers. This is maybe due to the fact that maybe, for instance, the language ScITE is editing does not have keywords.

I think that these concepts should be moved to the top level, so ScITE would know about keywords, identifiers and so on, and then the lexers would not have anything to do with colors, only maybe with specific symbols that are not dealt with by the top level.

This way, it would be possible to create different "style" files, light, dark, QBasic editor...

--
Baltasar

Red M

unread,
May 3, 2023, 5:30:50 PM5/3/23
to scite-i...@googlegroups.com
you depend on the lexer in order to set colors for keywords, identifiers, numbers...
Yes because SciTE isn't a lexer and to remove lexillia would be silly because then you'd have no lexers at all and so now you have no highlighting. 

This way, it would be possible to create different "style" files, light, dark, QBasic editor...
I already have done exactly that with the way SciTE already is using Lua scripts.

--
You received this message because you are subscribed to the Google Groups "scite-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scite-interes...@googlegroups.com.
Message has been deleted

Neil Hodgson

unread,
May 3, 2023, 6:54:54 PM5/3/23
to scite-interest
Baltasar:

> I think that these concepts should be moved to the top level, so ScITE would know about keywords, identifiers and so on, and then the lexers would not have anything to do with colors, only maybe with specific symbols that are not dealt with by the top level.
> This way, it would be possible to create different "style" files, light, dark, QBasic editor...

Lexers know nothing about colours: they assign a style number to each lexical class they understand. More recent lexers associate tags with each lexical class including "keyword", "operator", "comment", etc. These tags are not currently used in styling as they are not implemented on all lexers.

Multiple lexical classes may be representing similar types: Python has 8 literal string classes. Some people may like all these styled the same but others will prefer distinct styles. Many people want multiple sets of keywords (or known identifiers) with distinct styles. A theme system should not squash classes together for ease of implementation but should allow for gradual specialization both at theme definition and user customization levels.

Theme systems are often too-fragile, breaking when new classes are introduced as they would need to accommodate the new class in harmony with current styles. Theme authors are often only interested in a subset of languages they use and are unaware of nuances in other languages.

Neil

Neil Hodgson

unread,
May 3, 2023, 7:04:59 PM5/3/23
to scite-interest
Andrew Strain:

> I am trying to work out a patch for the dark mode feature but am stuck on correctly scoping
> a kind of global variable named `bool invertBrightness` so that it can be set when properties are in

Stick it on SciTEBase which is unfortunately huge as it is easy to access everywhere.

> I find it works nicely while being so short, a 'flaw' is that the result is less saturated than the original, however less saturation might even be aesthetic when lit on a dark background.

It's difficult to invert light consistently: colours near to white/black are commonly difficult and SciTE uses them a fair bit. For example, check Perl examples (like lexilla/test/examples/perl/perl-test-sub-prototypes.pl) to see how pastel background colours look. Its likely gamma curve related but may need special cases light colours.

Neil

andrew strain

unread,
May 3, 2023, 8:12:43 PM5/3/23
to scite-interest
> Stick it on SciTEBase

A bit bamboozled here by cpp's structure. I have `bool invertBrightness` declared in SciTEBase.h and set to false in SciTEBasec.cpp  and in SciTEProps.cxx it is set and compiles fine in void SciTEBase::SetPropertiesInitial. But I am trying to patch the transform into the methods in StyleDefinition.cxx  SA::Colour ColourFromString(  and the RGBA version of that function. But 'invertBrightness' was not declared in this scope.

If I can get the formulas running then I should be able to calibrate them to work reasonably well, I can use a longer version if its required to work on the perl syntax and tricky cases. I have used it alot to switch between daylight and after hours mood. I do not see anywhere else to put the transformation than those string conversion functions in StyleDefinition, perhaps it could go somewhere into Scintilla itself ?

Andrew

Neil Hodgson

unread,
May 3, 2023, 10:48:03 PM5/3/23
to scite-i...@googlegroups.com
Andrew:

> A bit bamboozled here by cpp's structure. I have `bool invertBrightness` declared in SciTEBase.h and set to false in SciTEBasec.cpp and in SciTEProps.cxx it is set and compiles fine in void SciTEBase::SetPropertiesInitial. But I am trying to patch the transform into the methods in StyleDefinition.cxx SA::Colour ColourFromString( and the RGBA version of that function. But 'invertBrightness' was not declared in this scope.

Changing ColourFromString may appear an attractive way to affect things globally but its bad modularity - ColourFromString performs a very simple job. You could modify callers to ColourFromString which will have access to SciTEBase or modify the output side sending data to scintilla like in SciTEBase::SetOneStyle.

> If I can get the formulas running then I should be able to calibrate them to work reasonably well, I can use a longer version if its required to work on the perl syntax and tricky cases. I have used it alot to switch between daylight and after hours mood. I do not see anywhere else to put the transformation than those string conversion functions in StyleDefinition, perhaps it could go somewhere into Scintilla itself ?

Scintilla works with colours a lot so each ColourRGBA instance would have to be modified which would be a significant amount of work. It's a bit similar to the old palette code which had to use a limited range (16 or 256 commonly) of available colours to cover the desired colours. Palette support was difficult to maintain and a source of bugs. A colour transform could be added to drawing surfaces in platform layers but that would need to be implemented for each platform.

Scintilla itself contains an InvertedLight function but it is only for printing in SC_PRINT_INVERTLIGHT mode used when the screen is set to a dark background but the user doesn't want to waste ink.

Neil

andrew strain

unread,
May 4, 2023, 9:49:00 AM5/4/23
to scite-interest
Looking into it a bit more, ColourFromString is called 14 times within StyleDefinition and SciteProps and once in SciTEbase. ColourAlphaFromString is called 9 times within StyleDefinition and SciTEProps.
These are functions which read text to determine desired colour, they happen to only understand hex rgb/a expressions. They each use the essentially simple functions ColourRGB() ColourRGBA() defined as inline constexpr's in StyleDefinition.h  which simply pack the values into the final low level colour word. ColourRGB() & A are used a handful of times outside of the two ColourFromString functions, to set default property values, those could neatly be changed to the string reading functions.  

Those sort of colour-expression-readers seem to be appropriate places to add any desired input transformation, like a transform to colour space, or in this case 'luminosity space'. With the transform function beside them and they each call it on their internal values if invertBrightness, before returning their output (which they use ColourRGB/A to pack).

If it was done in scintilla, it would seem required to take apart the rgba INTs as soon as they are recieved and transform and repack them before they are stored. Unlike the dark conversion for printing, they probably shouldnt be transformed for each render. And since a practical luminosity transformation cant be 'invertable' ( the very bright and dark values can't be converted back and forward ) - it cant be undone without a backup. It works out much simpler in SciTE with its speedy properties refreshing, to do the conversions at the point rgba's are determined from config text strings.

My lua script is evolved to do it very nicely though, its possible.

Im completely bamboozled by cpps scoping ways. Perhaps ColourAlphaFromString and Alpha' can be moved or namespace redesignated somehow so they can see invertBrightness ? The very simple ColourRGB() ColourRGBA() could be untouched.

Andrew

andrew strain

unread,
May 4, 2023, 5:15:58 PM5/4/23
to scite-interest
Sorry, more succinctly: ColourRGB() and ColourRGBA() perform a very simple clear job. ColourFromString and ColourAlphaFromString are not necessarily so generic, eg. they could be name ColourFromProperties and they could interpret text from properties circumspectly. All of the colours read by them should sooner or later be transformed when invertBrightness is true, it seems fitting to do it straight away.
I could make the inversion function return a single INT and call it InvertedColourRGBA() and have ColourFromString and ColourAlphaFromString use InvertedColourRGBA() instead of ColourRGBA() when dark mode is set.
Andrew

Neil Hodgson

unread,
May 4, 2023, 6:43:59 PM5/4/23
to scite-interest
Andrew:

> Sorry, more succinctly: ColourRGB() and ColourRGBA() perform a very simple clear job. ColourFromString and ColourAlphaFromString are not necessarily so generic, eg. they could be name ColourFromProperties and they could interpret text from properties circumspectly.

ColourFromProperties would carry some notion of context. ColourFromString is an isolated leaf function with no context dependence.

Performing the colour transformation in both ColourFromString and ColourAlphaFromString is repetition. Any transformation should be a separate function or method.

It is fine to hack a demonstration but not a finished feature.

Neil

andrew strain

unread,
May 5, 2023, 1:42:47 PM5/5/23
to scite-interest
Hello Neil,
I had quite a struggle defining and importing the dark mode status variable in different files and even tried moving concerned functions to ColourMapper.h/cxx but I kept getting mostly 'multiple definition' compilation errors, and ultimately failed. The way I see it dark mode in its very essence requires a non-literal interpretation of config colour strings. If that interpretation can not happen within the function which converts the colour strings to Scintilla colour type on properties refresh, then all the various colour data would need to be chased up and converted after properties refresh, somehow.
Around scite version 2.20 I had hacked the colour(alpha)fromstring functions to adapt to state to enable darkmode, contrast, and saturation adjustment. If there was any hack to allow it now, I would think it worthwhile to create a darkmode but the StyleDefinition object someways seems to guard against it.
Best wishes, Andrew

Neil Hodgson

unread,
May 5, 2023, 7:10:07 PM5/5/23
to scite-interest
Andrew:

The way I see it dark mode in its very essence requires a non-literal interpretation of config colour strings. If that interpretation can not happen within the function which converts the colour strings to Scintilla colour type on properties refresh, then all the various colour data would need to be chased up and converted after properties refresh, somehow.

Colour strings are not always resolved to colour integer values at read time. Properties are read and reread at different events in an effort to optimize performance.

Its likely that different contexts (edit pane, output pane, windows chrome, printing) will have different transformations.

Around scite version 2.20 I had hacked the colour(alpha)fromstring functions to adapt to state to enable darkmode, contrast, and saturation adjustment. If there was any hack to allow it now, I would think it worthwhile to create a darkmode but the StyleDefinition object someways seems to guard against it.

A non-hacky implementation will need to build infrastructure to support colour translations.

Perhaps start from this basic change to style fore and back. It also needs the default colours to be set explicitly (style.*.32=$(font.base),back:#FFFFFF,fore:#000000) since SciTE's standard properties provide differences from Scintilla's built-in black-on-white colours. This simple InvertLight function produces poor results in many cases.

Neil

diff -r 3b944ea15374 src/SciTEBase.h
--- a/src/SciTEBase.h Sat Apr 22 18:57:42 2023 +1000
+++ b/src/SciTEBase.h Sat May 06 08:46:59 2023 +1000
@@ -392,6 +392,8 @@
  bool wrapOutput;
  SA::Wrap wrapStyle;
  SA::IdleStyling idleStyling;
+ enum class ColourTranslation { none, invertLight } colourTranslation = ColourTranslation::invertLight;
+ SA::Colour TranslateColour(SA::Colour colour) const noexcept;
  SA::Alpha alphaIndicator;
  bool underIndicator;
  std::string foldColour;
diff -r 3b944ea15374 src/SciTEProps.cxx
--- a/src/SciTEProps.cxx Sat Apr 22 18:57:42 2023 +1000
+++ b/src/SciTEProps.cxx Sat May 06 08:46:59 2023 +1000
@@ -342,6 +342,27 @@
  return sd;
 }
 
+namespace {
+
+constexpr Scintilla::Colour InvertLight(Scintilla::Colour c) noexcept {
+ const unsigned int red = c & 0xffU;
+ const unsigned int green = (c >> 8) & 0xffU;
+ const unsigned int blue = (c >> 16) & 0xffU;
+ const unsigned int newRed = (green + blue) / 2;
+ const unsigned int newGreen = (red + blue) / 2;
+ const unsigned int newBlue = (red + green) / 2;
+ return ColourRGB(0xffU - newRed, 0xffU - newGreen, 0xffU - newBlue);
+}
+
+}
+
+Scintilla::Colour SciTEBase::TranslateColour(Scintilla::Colour colour) const noexcept {
+ if (colourTranslation == ColourTranslation::invertLight) {
+ return InvertLight(colour);
+ }
+ return colour;
+}
+
 void SciTEBase::SetOneStyle(GUI::ScintillaWindow &win, int style, std::string_view definition) {
  const StyleDefinition sd(definition);
  if (sd.specified & StyleDefinition::sdItalics)
@@ -357,9 +378,9 @@
  win.StyleSetCheckMonospaced(style, inMonospacedList);
  }
  if (sd.specified & StyleDefinition::sdFore)
- win.StyleSetFore(style, sd.Fore());
+ win.StyleSetFore(style, TranslateColour(sd.Fore()));
  if (sd.specified & StyleDefinition::sdBack)
- win.StyleSetBack(style, sd.Back());
+ win.StyleSetBack(style, TranslateColour(sd.Back()));
  if (sd.specified & StyleDefinition::sdSize)
  win.StyleSetSizeFractional(style, sd.FractionalSize());
  if (sd.specified & StyleDefinition::sdEOLFilled)

andrew strain

unread,
May 6, 2023, 9:20:46 AM5/6/23
to scite-interest
Neil :
I am very pleased to see how that is done. It is also remarkable how Scite can so snappily refresh the theme when my lua script rewrites the properties. The results of the simple formula was a bit lack luster on the perl theme but even it would be a relief to users with visual difficulties. I dug out my pre-lua function that was patched in for conversion and I think it can do better. It is an odd blob of code but works well to demonstrate.

https://gist.github.com/strainer/ca20642e9a091634f685915bd6b90e51

In my lua theme adjusting system, numerous styles have been ad-hoc re/defined from the rest of the properties in my user properties, and the ones which I use are masked with propertie symbols like $(th.greymauve). All the specials like, line nos, indent guides, even transparent indication of selections invert nicely. The transparent selection options may need tweaked to work nicely. With an inbuilt darkmode though, its much easier to cope with all the disparate language themes.

Andrew

Neil Hodgson

unread,
May 8, 2023, 8:00:43 PM5/8/23
to scite-interest
Andrew:

> It is also remarkable how Scite can so snappily refresh the theme when my lua script rewrites the properties.

There's an ongoing war between 'teh snappy' and expressiveness of properties files.

> The results of the simple formula was a bit lack luster on the perl theme but even it would be a relief to users with visual difficulties. I dug out my pre-lua function that was patched in for conversion and I think it can do better. It is an odd blob of code but works well to demonstrate.
>
> https://gist.github.com/strainer/ca20642e9a091634f685915bd6b90e51

That's a complex calculation. The results look much better than the simple formula. I hope the loop always terminates as that's not obvious to me.

The function can't be marked constexpr (potentially calculated at compile time) as abs is called and abs isn't defined as constexpr in the C++ standard until C++23 although some implementations may be constexpr. SciTE still has to support C++17.

Neil

andrew strain

unread,
May 8, 2023, 8:54:13 PM5/8/23
to scite-interest
Neil:
I can certainly remove the abs, and make the loop terminate more plainly, and improve the readability significantly I think. If avoiding abs or cmath like Math.pow, it is tempting to tweak the brightness 'flipping' to make it flip not around 50% but around 45% or 55% . That would be an approximate replacement for doing gamma correction in and out. Improvement would be very subtle but it only take an extra line or two. I can make a little project of making it much more readable.

An option is to have properties like this to expose finer control of the transform.
#rendering.transform.luminosity= -50 to 50
#rendering.transform.saturation= 0 to 100
#rendering.transform.brightness=-50 to 50

Or those configurables are just hard coded in the formula.
I think the optimal 'darkmode' transform for a white backed theme, would not actually produce a black background from a white input, instead a white -> dark charcoal, and black -> almost white. Constricting the target luminosity of the output like that, lets very dark or light colors reach their target with more color preserved. eg an input blue can be as dark as red or brown, but they cannot invert to an equally bright red or yellow, so dark blue wants to become white-ish, it loses alot of blueness to invert to equal standing with greens and yellows. Restricting the output helps, and over a very dark background, full white is not needed, the brightest grey on the screen becomes white. Most human made dark themes use dark grey, rarely black. A few folks might be perturbed if the dark mode wont produce pure black though.

I link below the reset for styles which I think dark mode will need explicit in properties. They are taken from my custom theme which is dark, but they are inverted to fit the default white backed theme.

https://gist.github.com/strainer/471ec624053923bd37a1829423d2e264

It seems caret, selection highlighting and fold margin colours will need programmed to transform.

- Andrew

andrew strain

unread,
May 10, 2023, 6:05:09 PM5/10/23
to scite-interest
Neil :
I think I have improved the effect of the function a bit more. Comments, style and some small formula improvements. cmath is avoided and abs removed so it could be a C++17 constexpr now.
It is calibrated to produce fully back background from full white and vice versa.
Very dark values of dark backgrounds are 'dragged' a little lighter to raise them a bit
- Andrew
Reply all
Reply to author
Forward
0 new messages