Skip to content

Commit 8d81a54

Browse files
committed
Implement Debug for Captures.
This shows what is, in my opinion, the most convenient display for capturing groups. That is, it is displayed as a map from capture slot or name to capture value. It omits slot numbers for named groups and omits offsets, but I think that's OK for a quick visual display. Closes #161.
1 parent 2cda56e commit 8d81a54

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/re_bytes.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,48 @@ impl<'t> Captures<'t> {
736736
}
737737
}
738738

739+
impl<'t> fmt::Debug for Captures<'t> {
740+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
741+
f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
742+
}
743+
}
744+
745+
struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
746+
747+
impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
748+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
749+
fn escape_bytes(bytes: &[u8]) -> String {
750+
let mut s = String::new();
751+
for &b in bytes {
752+
s.push_str(&escape_byte(b));
753+
}
754+
s
755+
}
756+
757+
fn escape_byte(byte: u8) -> String {
758+
use std::ascii::escape_default;
759+
760+
let escaped: Vec<u8> = escape_default(byte).collect();
761+
String::from_utf8_lossy(&escaped).into_owned()
762+
}
763+
764+
// We'd like to show something nice here, even if it means an
765+
// allocation to build a reverse index.
766+
let slot_to_name: HashMap<&usize, &String> =
767+
self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
768+
let mut map = f.debug_map();
769+
for (slot, m) in self.0.iter_pos().enumerate() {
770+
let m = m.map(|(s, e)| escape_bytes(&self.0.text[s..e]));
771+
if let Some(ref name) = slot_to_name.get(&slot) {
772+
map.entry(&name, &m);
773+
} else {
774+
map.entry(&slot, &m);
775+
}
776+
}
777+
map.finish()
778+
}
779+
}
780+
739781
/// Get a group by index.
740782
///
741783
/// `'t` is the lifetime of the matched text.

src/re_unicode.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,33 @@ impl<'t> Captures<'t> {
944944
}
945945
}
946946

947+
impl<'t> fmt::Debug for Captures<'t> {
948+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
949+
f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
950+
}
951+
}
952+
953+
struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
954+
955+
impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
956+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
957+
// We'd like to show something nice here, even if it means an
958+
// allocation to build a reverse index.
959+
let slot_to_name: HashMap<usize, &str> =
960+
self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
961+
let mut map = f.debug_map();
962+
for (slot, m) in self.0.iter_pos().enumerate() {
963+
let m = m.map(|(s, e)| &self.0.text[s..e]);
964+
if let Some(ref name) = slot_to_name.get(&slot) {
965+
map.entry(&name, &m);
966+
} else {
967+
map.entry(&slot, &m);
968+
}
969+
}
970+
map.finish()
971+
}
972+
}
973+
947974
/// Get a group by index.
948975
///
949976
/// `'t` is the lifetime of the matched text.

0 commit comments

Comments
 (0)