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

Support for variable-variables #790

Closed
wants to merge 5 commits into from
Closed

Conversation

jmgunn87
Copy link

The parser can now accept variable-variable declarations similar to that of php.
for example,

@vv1: var;
@vv2: vv1;
@vv3: vv2;
@@@vv3: var;

@vn: 1;
@vnv: vn;

.variable-variable{
  width: @@vnv;
  url: url('@{var}');
}

Unit tests are implemented and pass on my end. This would close a number of existing issues and requests for this feature and also I think the syntax is cleaner and more in-keeping with the style of the language than some of the other suggestions. The code implemented in rule.js that allows this needs benchmarking and can probably be optimized somewhat.

Hopefully this gets merged as I think this is an important feature that the language is lacking. If you want some more examples of where I think this feature has a real use please let me know as i'll post some code demonstrating my point.

Thanks.

@matthew-dean
Copy link
Member

I thought this was already supported? Isn't it listed on the LESS documentation page?

@jmgunn87
Copy link
Author

jmgunn87 commented May 8, 2012

I can't see it anywhere in the docs. Useful language feature or a waste of time?

@matthew-dean
Copy link
Member

On LESSCSS.org:

It is also possible to define variables with a variable name:

@Fnord: "I am fnord.";
@var: 'fnord';
content: @@var;

Isn't this the same thing?

@jmgunn87
Copy link
Author

jmgunn87 commented May 8, 2012

No. That feature only works for values. This patch allows property names to be declared in this way.
Copy and paste the example I put up in the pull request and try compiling it. It will give you a syntax error.
I should put some more use cases together which will show where this can be useful. When I get the time.

@lukeapage
Copy link
Member

Hi, some demo code showing usefulness would be useful - we are trying to keep things as simple as possible so would only like to extend the parser when it adds real value.. thanks.

@matthew-dean
Copy link
Member

Yes, I think we need demo code. Your comment, @jmgunn87, is that this works for property names, but I don't see an example of that.

@dmcass
Copy link
Contributor

dmcass commented Sep 5, 2012

Your test does exactly the same thing that @MatthewDL's example does.

@vn: 1;
@vnv: 'vn';              /* String instead of keyword */

.variable-variable{
  width: @@vnv;          /* works already */
  url: url('@{var}');    /* this should syntax error, @var is not defined */
}

I'm not sure what you're trying to accomplish at the top of your example, but it looks pretty cyclical and pointless for a test. If you're suggesting that @vv1: var should declare a variable @var whose value is the same as it's name, I highly disagree. This will inevitably lead to conflicts with CSS keywords. If not, can you please explain in more detail what you're trying to accomplish there?

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

@string: 'arbitraryName';
@@string: 100px;

A variable named arbitraryName now exists in the global scope. That's the simplest explanation of this feature. Can less do this at the moment? No, but it can do the following,

@arbitraryvalue: 'somestring';
@string: 'arbitraryValue';
@variable: @@arbitraryvalue;

This makes an assignment to an existing variable which is a very different thing.

My patch essentially allows strings as property names and is not an uncommon language feature(see php5).

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

Please try and run both examples using the current version of LESS so that you can understand what I am trying to achieve.

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

If the parser was built to allow variable value assignment, why not allow it to make variable variable declarations? It will allow the language way more flexibility and I'll happily maintain this as I'm actively developing against it already.

@dmcass
Copy link
Contributor

dmcass commented Sep 5, 2012

I don't think this syntax is explicit enough for declaring a new variable since the syntax already in use for keywords. With this PR, @foo: center creates a new variable @center: center which was not necessarily intended at all. If someone has a lot of variables for keywords in their LESS we're polluting the scope at which these variable-variables are declared with unnecessary, repetitive values. Variables must have values in LESS, and creating a variable whose value is the same as it's name is excessive and unnecessary. @red; should not compile to @red: red;.

As @agatronic and @MatthewDL have asked, please provide an example where this feature is actually useful.

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

You obviously are very confused. @foo: centre does not create @center: center. How have you come to that conclusion?

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

Have you actually tried the code I posted?

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

Where is it useful? #698

@dmcass
Copy link
Contributor

dmcass commented Sep 5, 2012

You're absolutely right, I was confused. I apologize for the misinformation. The example is needlessly verbose and confusing without providing an actual use case.

I did run your examples, neither of them compiles. I don't see a problem with this because neither of them accomplishes anything new.

Can you please demonstrate an example with input and output where this patch provides the ability to use variables as property names, such as the example from #698. I checked out the latest master from your fork and the following results in a syntax error. Please alter this to demonstrate how it would work with your PR.

.experimental(@property, @value) {
  -webkit-@property: @value;
  -moz-@property: @value;
  -ms-@property: @value;
  -o-@property: @value;
  @property: @value;
}

.borderRadius(@value) {
  .experimental(border-radius, @value);
}

article {
  .borderRadius(5px);
}

@lukeapage
Copy link
Member

yes, my concern is not how would this work and yes i totally agree lots of "languages" have it and I've found it useful in php... my question/concern is how does adding this language feature making writing css simpler.. what real world css writing problem does this solved (that we are not attempting to solve in a different way).

Because we could always say "is accessing variables via @@var useful? and if not, remove the functionality".. because complexity in less that doesn't bring usefulness is just complicating the code and long term development and mantainability...

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

@dmcass, stop being silly :p

@agatronic, Do I really need a use case? Aside from not having to rewrite parametric mixins that generate classes any time you want to reuse them, try adding all the "real word" use cases that the php implementation solves. This is not a domain level feature, moreover a language feature that will allow users to template their code which in turn reduces code duplication.

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

@webkitVar: '-webkit-whatever';
@@webkitVar: @value;

@jmgunn87
Copy link
Author

jmgunn87 commented Sep 5, 2012

#698 (comment)

@lukeapage
Copy link
Member

@jmgunn87 yes language feature have to be justified with at least a single valid real world example where they benefit a user.

it would be good to answer @dmcass and show how this feature and the property interpolation are related.

I'm all-for "a language feature that will allow users to template their code which in turn reduces code duplication".. just show us how this achieves that, because we haven't thought of any way it does as yet...

@lukeapage lukeapage closed this Sep 5, 2012
@lukeapage lukeapage reopened this Sep 5, 2012
@lukeapage
Copy link
Member

p.s. I give that example because php <> less... they are very different. as I understand it, Sass is closer to php than less and has lots of language features.. less is more declarative and tries to keep things simple so the user has no choice but producing stylesheets that are easier to follow and understand :)

@dmcass
Copy link
Contributor

dmcass commented Sep 5, 2012

Please show me what I'm doing wrong here. On your fork this compiles to no output. This assigns a variable, it doesn't allow one as a property name.

@webkitVar: '-webkit-foo';

.foo(@value) {
  @@webkitVar: @value;
}

div {
  .borderRadius(5px);
}

If you want some more examples of where I think this feature has a real use please let me know as i'll post some code demonstrating my point.

You said this in your original post. Please follow through. I'm not asking for the world, I'm asking for a working code example where this PR solves any real world problem or makes coding in LESS more efficient.

@lukeapage
Copy link
Member

I will re-open if anyone can come up with a valid real-world use-case.

@lukeapage lukeapage closed this Oct 28, 2012
@twisk
Copy link

twisk commented Nov 21, 2012

We would like this feature in orde to make it possible to create user defined functions and use the value in a variable variable name. I think it would solve the problem of user defined functions for many developers.

.transformColor(@var, @color)
{
@@var: someTransformation(@color);
}
p
{
.transformColor("pColor", green);
color: @pcolor;
}
{
.transformColor("bColor", red);
background-color: @bcolor;
}

@jmgunn87
Copy link
Author

jmgunn87 commented Dec 2, 2012

That's one good reason to reopen and pull.

@lukeapage
Copy link
Member

for that usecase wouldn't functions be better?

e.g. off the top of my head, if we allowed this...

@function mycolor(@a) contrast(@a, red, blue, 67%);

@twisk
Copy link

twisk commented Dec 3, 2012

That would be even better indeed! But I'm afraid that's more complicated to implement..

@crabilld
Copy link

I would so love this to get implemented. As I understand it, what I am trying to do is not currently possible in LESS. @lukeapage, here is a real world example of how I'm trying to use variable variables to make creating color shades easier:

.color-shades(@colors, @names, @i: length(@colors)) when (@i > 0) {
    .color-shades(@colors, @names, (@i - 1));
    @color: extract(@colors, @i);
    @name: extract(@names, @i);

    @@{name}-darker: darken(@color, 20%);
    @@{name}-dark: darken(@color, 10%);
    @@{name}: @color;
    @@{name}-light: lighten(@color, 10%);
    @@{name}-lighter: lighten(@color, 20%);
}
@color-names: color-red, color-green, color-blue;
@color-values: #f00, #0f0, #00f;
.color-shades(@color-values, @color-names);

That way, whenever I want to assign something a lighter shade of red, I just have to type "color: @color-red-lighter;" or "background: @color-red-lighter;" instead of writing out the lighten function and putting in the correct percent.
(BTW, the only reason I preceded the var names with "color-" is because LESS likes to convert those names into their hex forms... would like to know how to prevent that from happening)

@steven-pribilinskiy
Copy link

I needed it for a similar mixin which would assign a darker or lighter color depending on the input color. Here's an example

.darken-lighten(@property, @color, @percent) when (lightness(@color) >= 80%) {
    @@{property}: darken(@color, @percent);
}

.darken-lighten(@property, @color, @percent) when (lightness(@color) < 80%) {
    @@{property}: lighten(@color, @percent);
}
.darken-lighten(@secondary-link-color, @brand-secondary, 10%);

of course it would be much more concise if LESS would support ordinary functions with return value, then it could be accomplished like e.g.

.darken-lighten(@color, @percent) when (lightness(@color) >= 80%) {
    @return: darken(@color, @percent);
}
@secondary-link-color: .darken-lighten(@brand-secondary, 10%);

not even saying about having conditional statements at hand

@seven-phases-max
Copy link
Member

I needed it for a similar mixin which would assign a darker or lighter color depending on the input color.

See contrast.

@lukeapage
Copy link
Member

(BTW, the only reason I preceded the var names with "color-" is because
LESS likes to convert those names into their hex forms... would like to
know how to prevent that from happening)

It shouldn't happen any more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants