It is currently August 8th, 2020, 11:44 pm

[Suggestion] Enhancements to Include

Report bugs with the Rainmeter application and suggest features.
buckb
Posts: 38
Joined: February 12th, 2018, 12:47 am

[Suggestion] Enhancements to Include

Post by buckb »

A couple of suggestions to kick around.

Include with Substitution

Rainmeter skins often have repeated sections of code corresponding to repeated instances of a given object. A "Disk Drive" skin will have one or more instances of a disk drive, while a "Stock Quote" skin will have one or more instances of a stock quote. Using the stock quote skin as an example, a skin I have developed has a series of measures and meters that looks something like this:

Code: Select all

[measureNameStock1]
...
[measurePriceStock1]
...
[measureChangeStock1]
...

[meterNameStock1]
...
[meterPriceStock1]
...
[meterChangeStock1]
...
This set of measures and meters is then repeated for Stock2, Stock3, etc. Making a change to these stock objects requires repeated edits to each of the objects individually. To ease development and maintenance, I split these groupings of measures and meters into a series of includes:

Code: Select all

@IncludeS1=stock1.inc
@IncludeS2=stock2.inc
@IncludeS3=stock3.inc
Further, I code each of these includes to be identical, except for an instance number. I then automatically generate them. I start with a "master" include that looks like this:

Code: Select all

[measureNameStock$num$]
...
[measurePriceStock$num$]
...
[measureChangeStock$num$]
...

[meterNameStock$num$]
...
[meterPriceStock$num$]
...
[meterChangeStock$num$]
...
I then run a small cmd/vbscript that makes copies of the master include, and substitutes occurances of "$num$" with "1", "2", "3", etc. So when a change to the stock measures or meters is needed, I just change the master include, then regenerate the individual includes.

It occured to me that the use of a master include could be formalized with an enhancement to the Include syntax. For example, since Rainmeter already has a "Substitute" capability, we might have:

Code: Select all

@IncludeS1=stock.inc Substitute="$num$":"1"
@IncludeS2=stock.inc Substitute="$num$":"2"
@IncludeS3=stock.inc Substitute="$num$":"3"

Conditional Include

A common feature of skins that make use of repeated measures and meters is the need to conditionally enable or disable them. For example, if the stock skin discussed above can support 9 stocks, but a given user only wants to display 3 stocks, a common technique seems to be to code for 9 stocks, then selectively disable or hide their measures and meters.

For a skin that changes the number of display objects dynamically, disable/hide seems like the way to go. But for other skins, a conditional include mechanism could simplify the code by dispensing with the disables/hides:

Code: Select all

[Variables]
stockCount=3
symbol1=AAPL
symbol2=GOOG
symbol3=MSFT

...

@IncludeS1=stock.inc IncludeIf=(#stockCount# >= 1) Substitute="$num$":"1"
@IncludeS2=stock.inc IncludeIf=(#stockCount# >= 2) Substitute="$num$":"2"
@IncludeS3=stock.inc IncludeIf=(#stockCount# >= 3) Substitute="$num$":"3"
@IncludeS4=stock.inc IncludeIf=(#stockCount# >= 4) Substitute="$num$":"4"
@IncludeS5=stock.inc IncludeIf=(#stockCount# >= 5) Substitute="$num$":"5"
@IncludeS6=stock.inc IncludeIf=(#stockCount# >= 6) Substitute="$num$":"6"
@IncludeS7=stock.inc IncludeIf=(#stockCount# >= 7) Substitute="$num$":"7"
@IncludeS8=stock.inc IncludeIf=(#stockCount# >= 8) Substitute="$num$":"8"
@IncludeS9=stock.inc IncludeIf=(#stockCount# >= 9) Substitute="$num$":"9"
I couldn't think of a good keyword, but you get the idea. Only the first three includes would actually be incorporated into the skin.


I am undecided about the sugguestions I have just made. I am wary of encumbering Rainmeter's syntax, and complex substitutions or overuse of includes could make understanding a skin much more difficult. For now, I lean toward suggesting the include enhancements described here. I'd be curious to know if other skin developers have found alternate solutions to the issues I have discussed.


--buckb
User avatar
jsmorley
Developer
Posts: 21218
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [Suggestion] Enhancements to Include

Post by jsmorley »

It's just not how Rainmeter is engineered. Rainmeter is not a procedural programming language. There is only one "loop", the Update cycle. It's very simple. Inside the loop it pretty much just executes each Measure in turn, then updates each Meter in turn, then redraws the skin window.

So while I understand the charm of this, it's just not going to happen.

I could envision some external 3rd-party utility that offers some help of this type with "writing" skin files. Some tool that let's you create measures or meters that include some kind of "template" functionality, and when run the tool it would spit out a .ini file that automatically does all the duplication of the measures or meters for you. I'm not quite sure what this would look like, as it would need to be simple enough to use that it would be more attractive than just doing the relatively easy (If boring) copy and paste in a text editor. I'm a bit skeptical that it could gain any popularity, but you never know.

However, at the end of the day, a skin is a skin. We are just not going to go down the road of changing the architecture of Rainmeter, as that is a slippery-slope to a dark place.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

buckb wrote:
May 7th, 2018, 9:22 pm
I then run a small cmd/vbscript that makes copies of the master include, and substitutes occurances of "$num$" with "1", "2", "3", etc. So when a change to the stock measures or meters is needed, I just change the master include, then regenerate the individual includes.
You probably know you can do this in Rainmeter as well, by using a "counter" measure that incremements itself, and then execute one or more !WriteKeyValue bangs to the .inc files on every update of the measure, taking care to either disable the measure once you reach the maximum "$num$" or execute the bangs in an IfCondition, instead of an OnUpdate. When finished, you can refresh the skin so that the includes are "up to date" for usage.

That being said, if you only display one "stock quote" / "disk drive" information at a time (as oposed to all of them at once), then you absolutely don't need to create hundreds of measures and meters for this. One set is enough, as you'd easily be able to use dynamic variables to "jump" to the previous / next set. Example: if I have a stock quote skin and I want to display the 5 stock quotes all at once, I'd have to create 5 times the number of measures / meters for this; however, if I want to display only 1 stock quote at a time and jump to the previous / next using, say, mouse scroll, then only one set of these measures / meters would be needed.

As for the conditional includes, disabling / hiding through bangs is not that much of an annoyance, but if you still want to avoid it, you could simply set Disabled=($num$>#stockCount#) and Hidden=($num$>#stockCount#) to all the measures / meters in your include files and be done with it. As soon as you modify the #stockCount# variable in your skin, the measures / meters whose "index" is greater than stockCount will automatically disable / hide themselves.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

My impresion is that this would be a good place to use one or more Lua script measures, assuming Lua has the capabilities for it. Just saying...

That being said, I guess it's hard to maintain a balance between the relative simplicity of the Rainmeter's INI format (which already seems a bit complicated for the "regular" user) and the increased complexity of a procedural language (which, apart from requiring massive changes to Rainmeter, would be almost certainly a no-no for the said "regular" user). :confused:
User avatar
Brian
Developer
Posts: 2044
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: [Suggestion] Enhancements to Include

Post by Brian »

Suggestions similar to this have come up several times in the past.
https://forum.rainmeter.net/viewtopic.php?f=14&t=30136#p155080
https://forum.rainmeter.net/viewtopic.php?f=27&t=31193&p=158492#p158410
https://github.com/rainmeter/rainmeter/issues/214
https://github.com/rainmeter/rainmeter/issues/84 (sort of)
(probably more out there...)

At the end of the day, while most of these suggestions have some charm for skin authors/users that have a programming background - they offer very little to the average user that has no programming background. Some of these suggestions even break ini formatting rules, which we attempt to follow.

When adding new features, we attempt to keep the structure and syntax consistent with the rest of Rainmeter. Every object in a skin is defined by a [section] name, and subsequent key=value pairs. Nothing exists outside of that. This makes it really easy for users at any level to understand, modify, add, remove, and debug objects as they see fit. I can only imagine the support nightmare of users saying "I get an error from section XXX, but I cannot find it in the skin file" type of messages.

Incorporating any "procedural" non-ini formatted syntax is just going to confuse the bulk of our users.

I don't think any of the developers are against some sort of "dynamically created objects" or "repeating section creation" per se, I just think we haven't seen any idea that an average user can follow easily. We have added some fairly complicated items over the years such as measures: FileView, ActionTimer, and Lua scripts - and Container/Contained meters. A lot of users, even very experienced users, avoid these features alot of the time.

I agree with what jsmorley said, this seems like a better fit for a 3rd-party program/script that can "create" repeated sections from some sort of template and write to a ini skin file.

-Brian
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

Since we're at it, I'll add my (possibly, less "intrusive") bit to the repetition "issue" that this post (and probably others) refer to, given that it's a thing acknowledged by the devs. Why not allow some measure and meter options, similar to the Repeat parameter in ActionTimer and the @N notation, that handles this, like:

Code: Select all

[SomeMeasureOrMeter]
...regular measure or meter code...
Iterations = IterationStartNumber, IterationStep, IterationCount
IterationTarget = IterationVariable
...regular measure or meter code...
A simple usage scenario for this, in the case of a Calc measure:

Code: Select all

[ComputeSomething]
Measure=Calc
Formula=(#Number#)
Iterations=1,1,3
IterationTarget=Number
This would translate "internally" as:

Code: Select all

[ComputeSomething1]
Measure=Calc
Formula=1

[ComputeSomething2]
Measure=Calc
Formula=2

[ComputeSomething3]
Measure=Calc
Formula=3
When referring to the measures as section variables, the [ComputeSomething@N] notation would be used, like [ComputeSomething@1], [ComputeSomething@2] or [ComputeSomething@3], for example.

Anyway, as I said, personally I'm not particularly bothered by the repetition "issue" (probably because most of my skins generally avoid that, where they can), since it's not that hard to copy paste stuff in a text editor after all - just thought of contributing with an "alternative way" of doing this. I'm sure this isn't perfect and that is probably similar to what element suggested in a way, but I'm well aware that such modifications might cause additional problems if not implemented carefully - that's why I mentioned the need to have a way of referring to those "duplicated" measures / meters as section variables.

EDIT: Huh. I was just speculating when mentioning that Lua can be used for such tasks, but apparently the script(s) are more or less available in one of the links posted by element...
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

Brian wrote:
April 23rd, 2020, 9:01 am
I don't think any of the developers are against some sort of "dynamically created objects" or "repeating section creation" per se, I just think we haven't seen any idea that an average user can follow easily. We have added some fairly complicated items over the years such as measures: FileView, ActionTimer, and Lua scripts - and Container/Contained meters. A lot of users, even very experienced users, avoid these features alot of the time.
The Container option will, in my view, overcome this "adoption" hurdle eventually, simply because there is no other alternative that does what this does.
Brian wrote:
April 23rd, 2020, 9:01 am
Incorporating any "procedural" non-ini formatted syntax is just going to confuse the bulk of our users.
As it is now, there's probably a similar amount of "confusion" caused by the big number of measures / meters needed in some situations, for the bulk of Rainmeter users. Hence what I said before about the difficult task of balancing things between different type of approaches to this, for the devs ... :confused:
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

Another possible alternative, looking like the Loop measure: a new type of measure and meter, called, say, "Iterator" (could be "List", "Array", "Wrapper" or any other name, since "Container" or "Group" is taken). The measure would behave somewhat similarly to how a "parent" measure like WebParser or NowPlaying is behaving, and the meter similarly to how a Container is, with both of them being more or less "fake" / invisible and used just for creating the actual [ComputeSomethingN] / [DisplaySomethingN] measures and meters, respectively:

Code: Select all

[MeasureIterator]
Measure=Iterator
IterationStart=1
IterationStep=1
IterationCount=3
IterationTarget=SomeCounterVariable

[ComputeSomething]
Iterator=[MeasureIterator]
Measure=Calc
Formula=(#SomeCounterVariable#)

Code: Select all

[MeterIterator]
Meter=Iterator
X=(#IteratorLeft#)
IterationStart=1
IterationStep=1
IterationCount=3
IterationTarget=SomeCounterVariable

[DisplaySomething]
Iterator=MeterIterator
Meter=String
X=((#SomeCounterVariable#-0.5)*#ThisMeterWidth#)
StringAlign=Center
Text="Meter #SomeCounterVariable#"
DynamicVariables=1
Sorry for beating a dead horse here, but you know ... I'm never out of ideas of how to make the impossible possible. :lol: Feel free to dismiss these ideas if they lack or break something.
User avatar
jsmorley
Developer
Posts: 21218
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [Suggestion] Enhancements to Include

Post by jsmorley »

I really don't think "ego" plays any role in this project. Mostly we just have very few resources able to spend significant time in the actual code of the application, and so we look at things with a few criteria in mind.

Is the requested change something that would have broad appeal among either skin authors, skin users, or both? We are just not going to focus on some "nice to have" that is really, really wanted by one or two people, and of no interest to others.

Can this change be reasonably done in a way that protects our all-important commitment to backwards compatibility? This is always non-negotiable.

What is the impact of the change on resource usage? CPU, memory? What are the possible impacts on performance?

Does the change change in some fundamental way that Rainmeter "works" from a user-facing standpoint? We are not interesting in making Rainmeter any more complicated to use unless the benefit outweighs that cost. We are not going to look favorably on "kludges", "bags on the side of the machine", or anything that just doesn't feel like "Rainmeter". Rainmeter is not perfect by any means, but it is pretty good at what it does.

To be honest, it's the first criteria that almost always causes us to park what might be a perfectly reasonable idea. So often it is a change that makes something just a hair less "repetitive" for one or two skin authors, and while there is no reason to oppose that in principle, it's just not where we are going to focus our very limited time.

So I regret you are not satisfied with how ideas are received. I readily confess that when we see an idea that just doesn't interest us, we tend to "ignore" it, rather than get into a protracted back-and-forth about the relative merits of the idea, which pretty much always ends in someone being compared to Hitler.

I would point out that anyone who wants to is welcome to code any change to the source code they want, and submit a pull-request on Github. There is no certainty that doing that will ensure your change gets in, as ALL of the criteria above will still apply, but it is just in the nature of things that if we have some help in actually coding the change, it's going to make it easier to evaluate.
User avatar
Yincognito
Posts: 2200
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [Suggestion] Enhancements to Include

Post by Yincognito »

Ok, I'll try to walk on middle ground here and just ask, both element and jsmorley: isn't any way that such things can be implemented as a plugin? If it is, then problem solved: element will write it, and any user who wants to use it will use it, no strings attached. If it has a large following, maybe include it in the list of "built-in" Rainmeter plugins. Everybody goes home happy. ;-)

So, out of curiosity: could this behavior be implemented in a plugin, or is this changing how Rainmeter handles things too much and a Rainmeter fork is absolutely needed? :???: