Skip to content

Commit be66e43

Browse files
committed
servo: Merge #10749 - Prepare related files to make it easier to split up the Mako template (from servo:split-mako); r=nox
servo/servo#10586 (comment) r? nox Source-Repo: https://github.com/servo/servo Source-Revision: 3bfa4cc7414fea760ce5c503bfbcf25262acb9d7 UltraBlame original commit: 75af6f5e3e2d5876694d389cfcaf04de2120ab6e
1 parent 8cb38f3 commit be66e43

File tree

12 files changed

+414
-381
lines changed

12 files changed

+414
-381
lines changed

servo/components/style/build.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33

44

55
use std::env;
6-
use std::fs::File;
7-
use std::io::Write;
86
use std::path::Path;
9-
use std::process::{Command, Stdio, exit};
7+
use std::process::{Command, exit};
108

119
#[cfg(windows)]
1210
fn find_python() -> String {
@@ -31,25 +29,16 @@ fn find_python() -> String {
3129
}
3230

3331
fn main() {
34-
let python = match env::var("PYTHON") {
35-
Ok(python_path) => python_path,
36-
Err(_) => find_python(),
37-
};
38-
let style = Path::new(file!()).parent().unwrap();
39-
let mako = style.join("Mako-0.9.1.zip");
40-
let template = style.join("properties.mako.rs");
32+
let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
33+
let script = Path::new(file!()).parent().unwrap().join("properties").join("build.py");
4134
let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
42-
let result = Command::new(python)
43-
.env("PYTHONPATH", &mako)
44-
.env("TEMPLATE", &template)
45-
.env("PRODUCT", product)
46-
.arg("generate_properties_rs.py")
47-
.stderr(Stdio::inherit())
48-
.output()
35+
let status = Command::new(python)
36+
.arg(&script)
37+
.arg(product)
38+
.arg("style-crate")
39+
.status()
4940
.unwrap();
50-
if !result.status.success() {
41+
if !status.success() {
5142
exit(1)
5243
}
53-
let out = env::var("OUT_DIR").unwrap();
54-
File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap();
5544
}

servo/components/style/generate_properties_rs.py

Lines changed: 0 additions & 17 deletions
This file was deleted.

servo/components/style/list_properties.py

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
2+
3+
4+
5+
import json
6+
import os.path
7+
import sys
8+
9+
BASE = os.path.dirname(__file__)
10+
sys.path.insert(0, os.path.join(BASE, "Mako-0.9.1.zip"))
11+
12+
from mako import exceptions
13+
from mako.template import Template
14+
15+
import data
16+
17+
18+
def main():
19+
usage = "Usage: %s [ servo | gecko ] [ style-crate | geckolib | html ]" % sys.argv[0]
20+
if len(sys.argv) < 3:
21+
abort(usage)
22+
product = sys.argv[1]
23+
output = sys.argv[2]
24+
if product not in ["servo", "gecko"] or output not in ["style-crate", "geckolib", "html"]:
25+
abort(usage)
26+
27+
properties = data.PropertiesData(product=product)
28+
rust = render(os.path.join(BASE, "properties.mako.rs"), product=product, data=properties)
29+
if output == "style-crate":
30+
write(os.environ["OUT_DIR"], "properties.rs", rust)
31+
if output == "geckolib":
32+
template = os.path.join(BASE, "..", "..", "..", "ports", "geckolib", "properties.mako.rs")
33+
rust = render(template, data=properties)
34+
write(os.environ["OUT_DIR"], "properties.rs", rust)
35+
elif output == "html":
36+
write_html(properties)
37+
38+
39+
def abort(message):
40+
sys.stderr.write(message + b"\n")
41+
sys.exit(1)
42+
43+
44+
def render(filename, **context):
45+
try:
46+
template = Template(open(filename, "rb").read(),
47+
input_encoding="utf8",
48+
strict_undefined=True,
49+
filename=filename)
50+
51+
52+
return template.render(**context).encode("utf8")
53+
except:
54+
55+
56+
abort(exceptions.text_error_template().render().encode("utf8"))
57+
58+
59+
def write(directory, filename, content):
60+
if not os.path.exists(directory):
61+
os.makedirs(directory)
62+
open(os.path.join(directory, filename), "wb").write(content)
63+
64+
65+
def write_html(properties):
66+
properties = dict(
67+
(p.name, {
68+
"flag": p.experimental,
69+
"shorthand": hasattr(p, "sub_properties")
70+
})
71+
for p in properties.longhands + properties.shorthands
72+
)
73+
doc_servo = os.path.join(BASE, "..", "..", "..", "target", "doc", "servo")
74+
html = render(os.path.join(BASE, "properties.html.mako"), properties=properties)
75+
write(doc_servo, "css-properties.html", html)
76+
write(doc_servo, "css-properties.json", json.dumps(properties, indent=4))
77+
78+
79+
if __name__ == "__main__":
80+
main()
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
2+
3+
4+
5+
import re
6+
7+
8+
def to_rust_ident(name):
9+
name = name.replace("-", "_")
10+
if name in ["static", "super", "box", "move"]:
11+
name += "_"
12+
return name
13+
14+
15+
def to_camel_case(ident):
16+
return re.sub("_([a-z])", lambda m: m.group(1).upper(), ident.strip("_").capitalize())
17+
18+
19+
class Keyword(object):
20+
def __init__(self, name, values, gecko_constant_prefix=None,
21+
extra_gecko_values=None, extra_servo_values=None):
22+
self.name = name
23+
self.values = values
24+
self.gecko_constant_prefix = gecko_constant_prefix or \
25+
"NS_STYLE_" + self.name.upper().replace("-", "_")
26+
self.extra_gecko_values = (extra_gecko_values or "").split()
27+
self.extra_servo_values = (extra_servo_values or "").split()
28+
29+
def gecko_values(self):
30+
return self.values + self.extra_gecko_values
31+
32+
def servo_values(self):
33+
return self.values + self.extra_servo_values
34+
35+
def values_for(self, product):
36+
if product == "gecko":
37+
return self.gecko_values()
38+
elif product == "servo":
39+
return self.servo_values()
40+
else:
41+
raise Exception("Bad product: " + product)
42+
43+
def gecko_constant(self, value):
44+
return self.gecko_constant_prefix + "_" + value.upper().replace("-", "_")
45+
46+
47+
class Longhand(object):
48+
def __init__(self, style_struct, name, derived_from=None, keyword=None,
49+
custom_cascade=False, experimental=False, internal=False,
50+
gecko_ffi_name=None):
51+
self.name = name
52+
self.keyword = keyword
53+
self.ident = to_rust_ident(name)
54+
self.camel_case = to_camel_case(self.ident)
55+
self.style_struct = style_struct
56+
self.experimental = ("layout.%s.enabled" % name) if experimental else None
57+
self.custom_cascade = custom_cascade
58+
self.internal = internal
59+
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
60+
self.derived_from = (derived_from or "").split()
61+
62+
63+
class Shorthand(object):
64+
def __init__(self, name, sub_properties, experimental=False, internal=False):
65+
self.name = name
66+
self.ident = to_rust_ident(name)
67+
self.camel_case = to_camel_case(self.ident)
68+
self.derived_from = None
69+
self.experimental = ("layout.%s.enabled" % name) if experimental else None
70+
self.sub_properties = sub_properties
71+
self.internal = internal
72+
73+
74+
class Method(object):
75+
def __init__(self, name, return_type=None, arg_types=None, is_mut=False):
76+
self.name = name
77+
self.return_type = return_type
78+
self.arg_types = arg_types or []
79+
self.is_mut = is_mut
80+
81+
def arg_list(self):
82+
args = ["_: " + x for x in self.arg_types]
83+
args = ["&mut self" if self.is_mut else "&self"] + args
84+
return ", ".join(args)
85+
86+
def signature(self):
87+
sig = "fn %s(%s)" % (self.name, self.arg_list())
88+
if self.return_type:
89+
sig = sig + " -> " + self.return_type
90+
return sig
91+
92+
def declare(self):
93+
return self.signature() + ";"
94+
95+
def stub(self):
96+
return self.signature() + "{ unimplemented!() }"
97+
98+
99+
class StyleStruct(object):
100+
def __init__(self, name, inherited, gecko_ffi_name=None, additional_methods=None):
101+
self.servo_struct_name = "Servo" + name
102+
self.gecko_struct_name = "Gecko" + name
103+
self.trait_name = name
104+
self.trait_name_lower = name.lower()
105+
self.ident = to_rust_ident(self.trait_name_lower)
106+
self.longhands = []
107+
self.inherited = inherited
108+
self.gecko_ffi_name = gecko_ffi_name
109+
self.additional_methods = additional_methods or []
110+
111+
112+
class PropertiesData(object):
113+
def __init__(self, product):
114+
self.product = product
115+
self.style_structs = []
116+
self.current_style_struct = None
117+
self.longhands = []
118+
self.longhands_by_name = {}
119+
self.derived_longhands = {}
120+
self.shorthands = []
121+
122+
def new_style_struct(self, *args, **kwargs):
123+
style_struct = StyleStruct(*args, **kwargs)
124+
self.style_structs.append(style_struct)
125+
self.current_style_struct = style_struct
126+
127+
def active_style_structs(self):
128+
return [s for s in self.style_structs if s.additional_methods or s.longhands]
129+
130+
def switch_to_style_struct(self, name):
131+
for style_struct in self.style_structs:
132+
if style_struct.trait_name == name:
133+
self.current_style_struct = style_struct
134+
return
135+
raise Exception("Failed to find the struct named " + name)
136+
137+
def declare_longhand(self, name, products="gecko servo", **kwargs):
138+
products = products.split()
139+
if self.product not in products:
140+
return
141+
142+
longand = Longhand(self.current_style_struct, name, **kwargs)
143+
self.current_style_struct.longhands.append(longand)
144+
self.longhands.append(longand)
145+
self.longhands_by_name[name] = longand
146+
147+
for name in longand.derived_from:
148+
self.derived_longhands.setdefault(name, []).append(longand)
149+
150+
return longand
151+
152+
def declare_shorthand(self, name, sub_properties, *args, **kwargs):
153+
sub_properties = [self.longhands_by_name[s] for s in sub_properties]
154+
shorthand = Shorthand(name, sub_properties, *args, **kwargs)
155+
self.shorthands.append(shorthand)
156+
return shorthand

0 commit comments

Comments
 (0)