Adjust line number clearance (#5093)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
@ -1,6 +1,8 @@
|
|||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
use super::{distribute, Config, FlowResult, PlacedChild, Skip, Stop, Work};
|
use super::{
|
||||||
|
distribute, Config, FlowResult, LineNumberConfig, PlacedChild, Skip, Stop, Work,
|
||||||
|
};
|
||||||
use crate::diag::SourceResult;
|
use crate::diag::SourceResult;
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::foundations::{Content, NativeElement, Packed, Resolve, Smart};
|
use crate::foundations::{Content, NativeElement, Packed, Resolve, Smart};
|
||||||
@ -13,7 +15,7 @@ use crate::layout::{
|
|||||||
OuterHAlignment, PlacementScope, Point, Region, Regions, Rel, Size,
|
OuterHAlignment, PlacementScope, Point, Region, Regions, Rel, Size,
|
||||||
};
|
};
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
FootnoteElem, FootnoteEntry, LineNumberingScope, Numbering, ParLine, ParLineMarker,
|
FootnoteElem, FootnoteEntry, LineNumberingScope, Numbering, ParLineMarker,
|
||||||
};
|
};
|
||||||
use crate::syntax::Span;
|
use crate::syntax::Span;
|
||||||
use crate::utils::NonZeroExt;
|
use crate::utils::NonZeroExt;
|
||||||
@ -198,10 +200,11 @@ impl<'a, 'b> Composer<'a, 'b, '_, '_> {
|
|||||||
let mut output = insertions.finalize(self.work, self.config, inner);
|
let mut output = insertions.finalize(self.work, self.config, inner);
|
||||||
|
|
||||||
// Lay out per-column line numbers.
|
// Lay out per-column line numbers.
|
||||||
if self.config.root {
|
if let Some(line_config) = &self.config.line_numbers {
|
||||||
layout_line_numbers(
|
layout_line_numbers(
|
||||||
self.engine,
|
self.engine,
|
||||||
self.config,
|
self.config,
|
||||||
|
line_config,
|
||||||
locator,
|
locator,
|
||||||
self.column,
|
self.column,
|
||||||
&mut output,
|
&mut output,
|
||||||
@ -647,6 +650,7 @@ impl<'a, 'b> Insertions<'a, 'b> {
|
|||||||
fn layout_line_numbers(
|
fn layout_line_numbers(
|
||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
|
line_config: &LineNumberConfig,
|
||||||
locator: Locator,
|
locator: Locator,
|
||||||
column: usize,
|
column: usize,
|
||||||
output: &mut Frame,
|
output: &mut Frame,
|
||||||
@ -654,9 +658,7 @@ fn layout_line_numbers(
|
|||||||
let mut locator = locator.split();
|
let mut locator = locator.split();
|
||||||
|
|
||||||
// Reset page-scoped line numbers if currently at the first column.
|
// Reset page-scoped line numbers if currently at the first column.
|
||||||
if column == 0
|
if column == 0 && line_config.scope == LineNumberingScope::Page {
|
||||||
&& ParLine::numbering_scope_in(config.shared) == LineNumberingScope::Page
|
|
||||||
{
|
|
||||||
let reset = layout_line_number_reset(engine, config, &mut locator)?;
|
let reset = layout_line_number_reset(engine, config, &mut locator)?;
|
||||||
output.push_frame(Point::zero(), reset);
|
output.push_frame(Point::zero(), reset);
|
||||||
}
|
}
|
||||||
@ -711,9 +713,11 @@ fn layout_line_numbers(
|
|||||||
.resolve(config.shared)
|
.resolve(config.shared)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute the marker's horizontal position. Will be adjusted based on
|
// Determine how much space to leave between the column and the number.
|
||||||
// the maximum number width later.
|
let clearance = match marker.number_clearance {
|
||||||
let clearance = marker.number_clearance.resolve(config.shared);
|
Smart::Auto => line_config.default_clearance,
|
||||||
|
Smart::Custom(rel) => rel.resolve(config.shared),
|
||||||
|
};
|
||||||
|
|
||||||
// Compute the base X position.
|
// Compute the base X position.
|
||||||
let x = match margin {
|
let x = match margin {
|
||||||
|
@ -19,14 +19,14 @@ use self::compose::{compose, Composer};
|
|||||||
use self::distribute::distribute;
|
use self::distribute::distribute;
|
||||||
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
||||||
use crate::engine::{Engine, Route, Sink, Traced};
|
use crate::engine::{Engine, Route, Sink, Traced};
|
||||||
use crate::foundations::{Content, Packed, StyleChain};
|
use crate::foundations::{Content, Packed, Resolve, StyleChain};
|
||||||
use crate::introspection::{
|
use crate::introspection::{
|
||||||
Introspector, Location, Locator, LocatorLink, SplitLocator, Tag,
|
Introspector, Location, Locator, LocatorLink, SplitLocator, Tag,
|
||||||
};
|
};
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
Abs, Dir, Fragment, Frame, PlacementScope, Region, Regions, Rel, Size,
|
Abs, Dir, Em, Fragment, Frame, PageElem, PlacementScope, Region, Regions, Rel, Size,
|
||||||
};
|
};
|
||||||
use crate::model::{FootnoteElem, FootnoteEntry};
|
use crate::model::{FootnoteElem, FootnoteEntry, LineNumberingScope, ParLine};
|
||||||
use crate::realize::{realize, Arenas, Pair, RealizationKind};
|
use crate::realize::{realize, Arenas, Pair, RealizationKind};
|
||||||
use crate::text::TextElem;
|
use crate::text::TextElem;
|
||||||
use crate::utils::{NonZeroExt, Numeric};
|
use crate::utils::{NonZeroExt, Numeric};
|
||||||
@ -187,6 +187,18 @@ pub(crate) fn layout_flow(
|
|||||||
gap: FootnoteEntry::gap_in(shared),
|
gap: FootnoteEntry::gap_in(shared),
|
||||||
expand: regions.expand.x,
|
expand: regions.expand.x,
|
||||||
},
|
},
|
||||||
|
line_numbers: root.then(|| LineNumberConfig {
|
||||||
|
scope: ParLine::numbering_scope_in(shared),
|
||||||
|
default_clearance: {
|
||||||
|
let width = if PageElem::flipped_in(shared) {
|
||||||
|
PageElem::height_in(shared)
|
||||||
|
} else {
|
||||||
|
PageElem::width_in(shared)
|
||||||
|
};
|
||||||
|
(0.026 * width.unwrap_or_default())
|
||||||
|
.clamp(Em::new(0.75).resolve(shared), Em::new(2.5).resolve(shared))
|
||||||
|
},
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Collect the elements into pre-processed children. These are much easier
|
// Collect the elements into pre-processed children. These are much easier
|
||||||
@ -311,6 +323,8 @@ struct Config<'x> {
|
|||||||
columns: ColumnConfig,
|
columns: ColumnConfig,
|
||||||
/// Settings for footnotes.
|
/// Settings for footnotes.
|
||||||
footnote: FootnoteConfig,
|
footnote: FootnoteConfig,
|
||||||
|
/// Settings for line numbers.
|
||||||
|
line_numbers: Option<LineNumberConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration of footnotes.
|
/// Configuration of footnotes.
|
||||||
@ -338,6 +352,14 @@ struct ColumnConfig {
|
|||||||
dir: Dir,
|
dir: Dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration of line numbers.
|
||||||
|
struct LineNumberConfig {
|
||||||
|
/// Where line numbers are reset.
|
||||||
|
scope: LineNumberingScope,
|
||||||
|
/// The default clearance for `auto`.
|
||||||
|
default_clearance: Abs,
|
||||||
|
}
|
||||||
|
|
||||||
/// The result type for flow layout.
|
/// The result type for flow layout.
|
||||||
///
|
///
|
||||||
/// The `Err(_)` variant incorporate control flow events for finishing and
|
/// The `Err(_)` variant incorporate control flow events for finishing and
|
||||||
|
@ -7,7 +7,7 @@ use crate::foundations::{
|
|||||||
StyleVec, Unlabellable,
|
StyleVec, Unlabellable,
|
||||||
};
|
};
|
||||||
use crate::introspection::{Count, CounterUpdate, Locatable};
|
use crate::introspection::{Count, CounterUpdate, Locatable};
|
||||||
use crate::layout::{Abs, Em, HAlignment, Length, OuterHAlignment};
|
use crate::layout::{Em, HAlignment, Length, OuterHAlignment};
|
||||||
use crate::model::Numbering;
|
use crate::model::Numbering;
|
||||||
use crate::utils::singleton;
|
use crate::utils::singleton;
|
||||||
|
|
||||||
@ -219,17 +219,27 @@ impl Unlabellable for Packed<ParbreakElem> {}
|
|||||||
///
|
///
|
||||||
/// This element is exclusively used for line number configuration and cannot
|
/// This element is exclusively used for line number configuration and cannot
|
||||||
/// be placed.
|
/// be placed.
|
||||||
#[elem(name = "line", title = "Paragraph Line", Construct, Locatable)]
|
///
|
||||||
|
/// ```example
|
||||||
|
/// >>> #set page(margin: (left: 3em))
|
||||||
|
/// #set par.line(numbering: "1")
|
||||||
|
///
|
||||||
|
/// Roses are red. \
|
||||||
|
/// Violets are blue. \
|
||||||
|
/// Typst is there for you.
|
||||||
|
/// ```
|
||||||
|
#[elem(name = "line", title = "Paragraph Line", keywords = ["line numbering"], Construct, Locatable)]
|
||||||
pub struct ParLine {
|
pub struct ParLine {
|
||||||
/// How to number each line. Accepts a
|
/// How to number each line. Accepts a
|
||||||
/// [numbering pattern or function]($numbering).
|
/// [numbering pattern or function]($numbering).
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
/// #set par.line(numbering: "1")
|
/// >>> #set page(margin: (left: 3em))
|
||||||
|
/// #set par.line(numbering: "I")
|
||||||
///
|
///
|
||||||
/// Roses are red. \
|
/// Roses are red. \
|
||||||
/// Violets are blue. \
|
/// Violets are blue. \
|
||||||
/// Typst is awesome.
|
/// Typst is there for you.
|
||||||
/// ```
|
/// ```
|
||||||
#[ghost]
|
#[ghost]
|
||||||
pub numbering: Option<Numbering>,
|
pub numbering: Option<Numbering>,
|
||||||
@ -241,6 +251,7 @@ pub struct ParLine {
|
|||||||
/// the current text direction.
|
/// the current text direction.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
/// >>> #set page(margin: (left: 3em))
|
||||||
/// #set par.line(numbering: "I", number-align: left)
|
/// #set par.line(numbering: "I", number-align: left)
|
||||||
///
|
///
|
||||||
/// Hello world! \
|
/// Hello world! \
|
||||||
@ -253,6 +264,7 @@ pub struct ParLine {
|
|||||||
/// The margin at which line numbers appear.
|
/// The margin at which line numbers appear.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
/// >>> #set page(margin: (right: 3em))
|
||||||
/// #set par.line(numbering: "1", number-margin: right)
|
/// #set par.line(numbering: "1", number-margin: right)
|
||||||
///
|
///
|
||||||
/// = Report
|
/// = Report
|
||||||
@ -265,10 +277,14 @@ pub struct ParLine {
|
|||||||
|
|
||||||
/// The distance between line numbers and text.
|
/// The distance between line numbers and text.
|
||||||
///
|
///
|
||||||
|
/// The default value of `{auto}` results in a clearance that is adaptive to
|
||||||
|
/// the page width and yields reasonable results in most cases.
|
||||||
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
/// >>> #set page(margin: (left: 3em))
|
||||||
/// #set par.line(
|
/// #set par.line(
|
||||||
/// numbering: "1",
|
/// numbering: "1",
|
||||||
/// number-clearance: 0.5pt
|
/// number-clearance: 4pt
|
||||||
/// )
|
/// )
|
||||||
///
|
///
|
||||||
/// Typesetting \
|
/// Typesetting \
|
||||||
@ -276,8 +292,8 @@ pub struct ParLine {
|
|||||||
/// Layout
|
/// Layout
|
||||||
/// ```
|
/// ```
|
||||||
#[ghost]
|
#[ghost]
|
||||||
#[default(Length::from(Abs::cm(1.0)))]
|
#[default]
|
||||||
pub number_clearance: Length,
|
pub number_clearance: Smart<Length>,
|
||||||
|
|
||||||
/// Controls when to reset line numbering.
|
/// Controls when to reset line numbering.
|
||||||
///
|
///
|
||||||
@ -285,8 +301,9 @@ pub struct ParLine {
|
|||||||
/// is never reset, or `"page"`, indicating it is reset on every page.
|
/// is never reset, or `"page"`, indicating it is reset on every page.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
/// >>> #set page(margin: (left: 3em))
|
||||||
/// #set par.line(
|
/// #set par.line(
|
||||||
/// numbering: "1.",
|
/// numbering: "1",
|
||||||
/// numbering-scope: "page"
|
/// numbering-scope: "page"
|
||||||
/// )
|
/// )
|
||||||
///
|
///
|
||||||
@ -339,7 +356,7 @@ pub struct ParLineMarker {
|
|||||||
|
|
||||||
#[internal]
|
#[internal]
|
||||||
#[required]
|
#[required]
|
||||||
pub number_clearance: Length,
|
pub number_clearance: Smart<Length>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Construct for ParLineMarker {
|
impl Construct for ParLineMarker {
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 910 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 464 B |
@ -1,5 +1,5 @@
|
|||||||
--- line-numbers-enable ---
|
--- line-numbers-enable ---
|
||||||
#set page(margin: (left: 1.5cm))
|
#set page(margin: (left: 2.5em))
|
||||||
#set par.line(numbering: "1")
|
#set par.line(numbering: "1")
|
||||||
|
|
||||||
First line \
|
First line \
|
||||||
@ -23,13 +23,13 @@ Second line \
|
|||||||
Third line
|
Third line
|
||||||
|
|
||||||
--- line-numbers-default-alignment ---
|
--- line-numbers-default-alignment ---
|
||||||
#set page(margin: (left: 2cm))
|
#set page(margin: (left: 3em))
|
||||||
#set par.line(numbering: "1")
|
#set par.line(numbering: "1")
|
||||||
a
|
a
|
||||||
#([\ a] * 15)
|
#([\ a] * 15)
|
||||||
|
|
||||||
--- line-numbers-start-alignment ---
|
--- line-numbers-start-alignment ---
|
||||||
#set page(margin: (left: 2cm))
|
#set page(margin: (left: 3em))
|
||||||
#set par.line(numbering: "i", number-align: start)
|
#set par.line(numbering: "i", number-align: start)
|
||||||
a \
|
a \
|
||||||
a
|
a
|
||||||
@ -47,7 +47,7 @@ Second line \
|
|||||||
Third line
|
Third line
|
||||||
|
|
||||||
--- line-numbers-rtl ---
|
--- line-numbers-rtl ---
|
||||||
#set page(margin: (right: 2cm))
|
#set page(margin: (right: 3em))
|
||||||
#set text(dir: rtl)
|
#set text(dir: rtl)
|
||||||
#set par.line(numbering: "1")
|
#set par.line(numbering: "1")
|
||||||
a
|
a
|
||||||
@ -120,7 +120,7 @@ In the \
|
|||||||
Sky
|
Sky
|
||||||
|
|
||||||
--- line-numbers-page-scope ---
|
--- line-numbers-page-scope ---
|
||||||
#set page(margin: (left: 2cm))
|
#set page(margin: (left: 2.5em))
|
||||||
#set par.line(numbering: "1", numbering-scope: "page")
|
#set par.line(numbering: "1", numbering-scope: "page")
|
||||||
|
|
||||||
First line \
|
First line \
|
||||||
|