just playing with tangled
at diffedit3 117 lines 3.4 kB view raw
1// Copyright 2020 The Jujutsu Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15use std::hash::Hash; 16use std::io; 17use std::io::Write; 18 19use itertools::Itertools; 20use jj_lib::settings::UserSettings; 21use renderdag::{Ancestor, GraphRowRenderer, Renderer}; 22 23#[derive(Debug, Clone, PartialEq, Eq)] 24// An edge to another node in the graph 25pub enum Edge<T> { 26 Direct(T), 27 Indirect(T), 28 Missing, 29} 30 31pub trait GraphLog<K: Clone + Eq + Hash> { 32 fn add_node( 33 &mut self, 34 id: &K, 35 edges: &[Edge<K>], 36 node_symbol: &str, 37 text: &str, 38 ) -> io::Result<()>; 39 40 fn width(&self, id: &K, edges: &[Edge<K>]) -> usize; 41} 42 43pub struct SaplingGraphLog<'writer, R> { 44 renderer: R, 45 writer: &'writer mut dyn Write, 46} 47 48impl<K: Clone> From<&Edge<K>> for Ancestor<K> { 49 fn from(e: &Edge<K>) -> Self { 50 match e { 51 Edge::Direct(target) => Ancestor::Parent(target.clone()), 52 Edge::Indirect(target) => Ancestor::Ancestor(target.clone()), 53 Edge::Missing => Ancestor::Anonymous, 54 } 55 } 56} 57 58impl<'writer, K, R> GraphLog<K> for SaplingGraphLog<'writer, R> 59where 60 K: Clone + Eq + Hash, 61 R: Renderer<K, Output = String>, 62{ 63 fn add_node( 64 &mut self, 65 id: &K, 66 edges: &[Edge<K>], 67 node_symbol: &str, 68 text: &str, 69 ) -> io::Result<()> { 70 let row = self.renderer.next_row( 71 id.clone(), 72 edges.iter().map_into().collect(), 73 node_symbol.into(), 74 text.into(), 75 ); 76 77 write!(self.writer, "{row}") 78 } 79 80 fn width(&self, id: &K, edges: &[Edge<K>]) -> usize { 81 let parents = edges.iter().map_into().collect(); 82 let w: u64 = self.renderer.width(Some(id), Some(&parents)); 83 w.try_into().unwrap() 84 } 85} 86 87impl<'writer, R> SaplingGraphLog<'writer, R> { 88 pub fn create<K>( 89 renderer: R, 90 formatter: &'writer mut dyn Write, 91 ) -> Box<dyn GraphLog<K> + 'writer> 92 where 93 K: Clone + Eq + Hash + 'writer, 94 R: Renderer<K, Output = String> + 'writer, 95 { 96 Box::new(SaplingGraphLog { 97 renderer, 98 writer: formatter, 99 }) 100 } 101} 102 103pub fn get_graphlog<'a, K: Clone + Eq + Hash + 'a>( 104 settings: &UserSettings, 105 formatter: &'a mut dyn Write, 106) -> Box<dyn GraphLog<K> + 'a> { 107 let builder = GraphRowRenderer::new().output().with_min_row_height(0); 108 match settings.graph_style().as_str() { 109 "square" => { 110 SaplingGraphLog::create(builder.build_box_drawing().with_square_glyphs(), formatter) 111 } 112 "ascii" => SaplingGraphLog::create(builder.build_ascii(), formatter), 113 "ascii-large" => SaplingGraphLog::create(builder.build_ascii_large(), formatter), 114 // "curved" 115 _ => SaplingGraphLog::create(builder.build_box_drawing(), formatter), 116 } 117}