diff --git a/components/plugins/casing.rs b/components/plugins/casing.rs new file mode 100644 index 00000000000..374290f3cbb --- /dev/null +++ b/components/plugins/casing.rs @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use syntax::ext::base::ExtCtxt; +use syntax::ext::build::AstBuilder; +use syntax::codemap::Span; +use syntax::ast; +use syntax::ext::base; +use syntax::parse::token; + +pub fn expand_lower<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) + -> Box { + expand_cased(cx, sp, tts, |c| { c.to_lowercase() }) +} + +pub fn expand_upper<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) + -> Box { + expand_cased(cx, sp, tts, |c| { c.to_uppercase() }) +} + +fn expand_cased<'cx, T>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree], transform: T) + -> Box + where T: Fn(char) -> char +{ + let es = match base::get_exprs_from_tts(cx, sp, tts) { + Some(e) => e, + None => return base::DummyResult::expr(sp) + }; + + let mut it = es.iter(); + let res = if let Some(expr) = it.next() { + if let ast::ExprLit(ref lit) = expr.node { + if let ast::LitStr(ref s, _) = lit.node { + Some((s, lit.span)) + } else { + cx.span_err(expr.span, "expected a string literal"); + None + } + } else { + cx.span_err(expr.span, "expected a string literal"); + None + } + } else { + cx.span_err(sp, "expected 1 argument, found 0"); + None + }; + match (res, it.count()) { + (Some((s, span)), 0) => { + let new_s = s.get().chars().map(transform).collect::(); + base::MacExpr::new(cx.expr_str(span, token::intern_and_get_ident(new_s.as_slice()))) + } + (_, rest) => { + if rest > 0 { + cx.span_err(sp, format!("expected 1 argument, found {}", rest+1).as_slice()); + } + base::DummyResult::expr(sp) + } + } +} diff --git a/components/plugins/lib.rs b/components/plugins/lib.rs index 6190114ac39..ede81332fab 100644 --- a/components/plugins/lib.rs +++ b/components/plugins/lib.rs @@ -40,12 +40,15 @@ pub mod reflector; pub mod lints; /// Utilities for writing plugins pub mod utils; +pub mod casing; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension(intern("dom_struct"), Modifier(box jstraceable::expand_dom_struct)); reg.register_syntax_extension(intern("jstraceable"), Decorator(box jstraceable::expand_jstraceable)); reg.register_syntax_extension(intern("_generate_reflector"), Decorator(box reflector::expand_reflector)); + reg.register_macro("to_lower", casing::expand_lower); + reg.register_macro("to_upper", casing::expand_upper); reg.register_lint_pass(box lints::transmute_type::TransmutePass as LintPassObject); reg.register_lint_pass(box lints::unrooted_must_root::UnrootedPass as LintPassObject); reg.register_lint_pass(box lints::privatize::PrivatizePass as LintPassObject); diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 30759c3bed0..d00aa9961b1 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -11,11 +11,11 @@ macro_rules! make_getter( #[allow(unused_imports)] use std::ascii::AsciiExt; let element: JSRef = ElementCast::from_ref(self); - element.get_string_attribute(&Atom::from_slice($htmlname.to_ascii_lowercase().as_slice())) + element.get_string_attribute(&Atom::from_slice($htmlname)) } ); ($attr:ident) => { - make_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice()); + make_getter!($attr, to_lower!(stringify!($attr))); } ); @@ -33,7 +33,7 @@ macro_rules! make_bool_getter( } ); ($attr:ident) => { - make_bool_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice()); + make_bool_getter!($attr, to_lower!(stringify!($attr))); } ); @@ -51,7 +51,7 @@ macro_rules! make_uint_getter( } ); ($attr:ident) => { - make_uint_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice()); + make_uint_getter!($attr, to_lower!(stringify!($attr))); } ); @@ -70,7 +70,7 @@ macro_rules! make_url_getter( ); ($attr:ident) => { // FIXME(pcwalton): Do this at compile time, not runtime. - make_url_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice()); + make_url_getter!($attr, to_lower!(stringify!($attr))); } ); @@ -94,7 +94,7 @@ macro_rules! make_url_or_base_getter( } ); ($attr:ident) => { - make_url_or_base_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice()); + make_url_or_base_getter!($attr, to_lower!(stringify!($attr))); } ); @@ -118,7 +118,7 @@ macro_rules! make_enumerated_getter( } ); ($attr:ident, $default:expr, $(($choices: pat))|+) => { - make_enumerated_getter!($attr, stringify!($attr).to_ascii_lowercase().as_slice(), $default, $(($choices))|+); + make_enumerated_getter!($attr, to_lower!(stringify!($attr)).as_slice(), $default, $(($choices))|+); } );