pub struct LoroDoc { /* private fields */ }
Expand description
LoroDoc
serves as the library’s primary entry point.
It’s constituted by an OpLog and an DocState.
- OpLog encompasses all operations, signifying the document history.
- DocState signifies the current document state.
They will share a [super::arena::SharedArena]
§Detached Mode
This mode enables separate usage of OpLog and DocState. It facilitates temporal navigation. DocState can be reverted to any version contained within the OpLog.
LoroDoc::detach()
separates DocState from OpLog. In this mode,
updates to OpLog won’t affect DocState, while updates to DocState
will continue to affect OpLog.
Implementations§
Source§impl LoroDoc
impl LoroDoc
Sourcepub fn decode_import_blob_meta(
blob: &[u8],
check_checksum: bool,
) -> LoroResult<ImportBlobMetadata>
pub fn decode_import_blob_meta( blob: &[u8], check_checksum: bool, ) -> LoroResult<ImportBlobMetadata>
Decodes the metadata for an imported blob from the provided bytes.
Source§impl LoroDoc
impl LoroDoc
pub fn new() -> Self
pub fn fork(&self) -> Self
Sourcepub fn set_detached_editing(&self, enable: bool)
pub fn set_detached_editing(&self, enable: bool)
Enables editing of the document in detached mode.
By default, the document cannot be edited in detached mode (after calling
detach
or checking out a version other than the latest). This method
allows editing in detached mode.
§Important Notes:
- After enabling this mode, the document will use a different PeerID. Each time you call checkout, a new PeerID will be used.
- If you set a custom PeerID while this mode is enabled, ensure that concurrent operations with the same PeerID are not possible.
- On detached mode, importing will not change the state of the document.
It also doesn’t change the version of the DocState. The changes will be
recorded into OpLog only. You need to call
checkout
to make it take effect.
Sourcepub fn new_auto_commit() -> Self
pub fn new_auto_commit() -> Self
Create a doc with auto commit enabled.
pub fn set_peer_id(&self, peer: PeerID) -> LoroResult<()>
Sourcepub fn commit_then_stop(
&self,
) -> (Option<CommitOptions>, LoroMutexGuard<'_, Option<Transaction>>)
pub fn commit_then_stop( &self, ) -> (Option<CommitOptions>, LoroMutexGuard<'_, Option<Transaction>>)
Commit the cumulative auto commit transaction.
This method only has effect when auto_commit
is true.
Afterwards, the users need to call self.renew_txn_after_commit()
to resume the continuous transaction.
It only returns Some(options_of_the_empty_txn) when the txn is empty
Sourcepub fn commit_then_renew(&self) -> Option<CommitOptions>
pub fn commit_then_renew(&self) -> Option<CommitOptions>
Commit the cumulative auto commit transaction. It will start the next one immediately
It only returns Some(options_of_the_empty_txn) when the txn is empty
Sourcepub fn commit_with(
&self,
config: CommitOptions,
) -> (Option<CommitOptions>, Option<LoroMutexGuard<'_, Option<Transaction>>>)
pub fn commit_with( &self, config: CommitOptions, ) -> (Option<CommitOptions>, Option<LoroMutexGuard<'_, Option<Transaction>>>)
Commit the cumulative auto commit transaction.
This method only has effect when auto_commit
is true.
If immediate_renew
is true, a new transaction will be created after the old one is committed
It only returns Some(options_of_the_empty_txn) when the txn is empty
Sourcepub fn set_next_commit_message(&self, message: &str)
pub fn set_next_commit_message(&self, message: &str)
Set the commit message of the next commit
Sourcepub fn set_next_commit_origin(&self, origin: &str)
pub fn set_next_commit_origin(&self, origin: &str)
Set the origin of the next commit
Sourcepub fn set_next_commit_timestamp(&self, timestamp: Timestamp)
pub fn set_next_commit_timestamp(&self, timestamp: Timestamp)
Set the timestamp of the next commit
Sourcepub fn set_next_commit_options(&self, options: CommitOptions)
pub fn set_next_commit_options(&self, options: CommitOptions)
Set the options of the next commit
Sourcepub fn clear_next_commit_options(&self)
pub fn clear_next_commit_options(&self)
Clear the options of the next commit
Sourcepub fn set_record_timestamp(&self, record: bool)
pub fn set_record_timestamp(&self, record: bool)
Set whether to record the timestamp of each change. Default is false
.
If enabled, the Unix timestamp will be recorded for each change automatically.
You can also set each timestamp manually when you commit a change. The timestamp manually set will override the automatic one.
NOTE: Timestamps are forced to be in ascending order. If you commit a new change with a timestamp that is less than the existing one, the largest existing timestamp will be used instead.
Sourcepub fn set_change_merge_interval(&self, interval: i64)
pub fn set_change_merge_interval(&self, interval: i64)
Set the interval of mergeable changes, in seconds.
If two continuous local changes are within the interval, they will be merged into one change. The default value is 1000 seconds.
pub fn can_edit(&self) -> bool
pub fn is_detached_editing_enabled(&self) -> bool
pub fn config_text_style(&self, text_style: StyleConfigMap)
pub fn config_default_text_style(&self, text_style: Option<StyleConfig>)
pub fn from_snapshot(bytes: &[u8]) -> LoroResult<Self>
Sourcepub fn can_reset_with_snapshot(&self) -> bool
pub fn can_reset_with_snapshot(&self) -> bool
Is the document empty? (no ops)
Sourcepub fn is_detached(&self) -> bool
pub fn is_detached(&self) -> bool
pub fn peer_id(&self) -> PeerID
pub fn detach(&self)
pub fn attach(&self)
Sourcepub fn state_timestamp(&self) -> Timestamp
pub fn state_timestamp(&self) -> Timestamp
Get the timestamp of the current state. It’s the last edit time of the DocState.
pub fn app_state(&self) -> &Arc<LoroMutex<DocState>>
pub fn get_state_deep_value(&self) -> LoroValue
pub fn oplog(&self) -> &Arc<LoroMutex<OpLog>>
pub fn export_from(&self, vv: &VersionVector) -> Vec<u8> ⓘ
pub fn import(&self, bytes: &[u8]) -> Result<ImportStatus, LoroError>
pub fn import_with( &self, bytes: &[u8], origin: InternalString, ) -> Result<ImportStatus, LoroError>
pub fn export_snapshot(&self) -> Result<Vec<u8>, LoroEncodeError>
Sourcepub fn import_json_updates<T: TryInto<JsonSchema>>(
&self,
json: T,
) -> LoroResult<ImportStatus>
pub fn import_json_updates<T: TryInto<JsonSchema>>( &self, json: T, ) -> LoroResult<ImportStatus>
Import the json schema updates.
only supports backward compatibility but not forward compatibility.
pub fn export_json_updates( &self, start_vv: &VersionVector, end_vv: &VersionVector, with_peer_compression: bool, ) -> JsonSchema
pub fn export_json_in_id_span(&self, id_span: IdSpan) -> Vec<JsonChange>
Sourcepub fn oplog_vv(&self) -> VersionVector
pub fn oplog_vv(&self) -> VersionVector
Get the version vector of the current OpLog
Sourcepub fn state_vv(&self) -> VersionVector
pub fn state_vv(&self) -> VersionVector
Get the version vector of the current DocState
pub fn get_by_path(&self, path: &[Index]) -> Option<ValueOrHandler>
Sourcepub fn get_by_str_path(&self, path: &str) -> Option<ValueOrHandler>
pub fn get_by_str_path(&self, path: &str) -> Option<ValueOrHandler>
Get the handler by the string path.
pub fn get_uncommitted_ops_as_json(&self) -> Option<JsonSchema>
pub fn get_handler(&self, id: ContainerID) -> Option<Handler>
Sourcepub fn get_text<I: IntoContainerId>(&self, id: I) -> TextHandler
pub fn get_text<I: IntoContainerId>(&self, id: I) -> TextHandler
id can be a str, ContainerID, or ContainerIdRaw. if it’s str it will use Root container, which will not be None
Sourcepub fn get_list<I: IntoContainerId>(&self, id: I) -> ListHandler
pub fn get_list<I: IntoContainerId>(&self, id: I) -> ListHandler
id can be a str, ContainerID, or ContainerIdRaw. if it’s str it will use Root container, which will not be None
Sourcepub fn get_movable_list<I: IntoContainerId>(&self, id: I) -> MovableListHandler
pub fn get_movable_list<I: IntoContainerId>(&self, id: I) -> MovableListHandler
id can be a str, ContainerID, or ContainerIdRaw. if it’s str it will use Root container, which will not be None
Sourcepub fn get_map<I: IntoContainerId>(&self, id: I) -> MapHandler
pub fn get_map<I: IntoContainerId>(&self, id: I) -> MapHandler
id can be a str, ContainerID, or ContainerIdRaw. if it’s str it will use Root container, which will not be None
Sourcepub fn get_tree<I: IntoContainerId>(&self, id: I) -> TreeHandler
pub fn get_tree<I: IntoContainerId>(&self, id: I) -> TreeHandler
id can be a str, ContainerID, or ContainerIdRaw. if it’s str it will use Root container, which will not be None
pub fn has_container(&self, id: &ContainerID) -> bool
Sourcepub fn undo_internal(
&self,
id_span: IdSpan,
container_remap: &mut FxHashMap<ContainerID, ContainerID>,
post_transform_base: Option<&DiffBatch>,
before_diff: &mut dyn FnMut(&DiffBatch),
) -> LoroResult<CommitWhenDrop<'_>>
pub fn undo_internal( &self, id_span: IdSpan, container_remap: &mut FxHashMap<ContainerID, ContainerID>, post_transform_base: Option<&DiffBatch>, before_diff: &mut dyn FnMut(&DiffBatch), ) -> LoroResult<CommitWhenDrop<'_>>
Undo the operations between the given id_span. It can be used even in a collaborative environment.
This is an internal API. You should NOT use it directly.
§Internal
This method will use the diff calculator to calculate the diff required to time travel from the end of id_span to the beginning of the id_span. Then it will convert the diff to operations and apply them to the OpLog with a dep on the last id of the given id_span.
This implementation is kinda slow, but it’s simple and maintainable. We can optimize it further when it’s needed. The time complexity is O(n + m), n is the ops in the id_span, m is the distance from id_span to the current latest version.
Sourcepub fn revert_to(&self, target: &Frontiers) -> LoroResult<()>
pub fn revert_to(&self, target: &Frontiers) -> LoroResult<()>
Generate a series of local operations that can revert the current doc to the target version.
Internally, it will calculate the diff between the current state and the target state, and apply the diff to the current state.
Sourcepub fn diff(&self, a: &Frontiers, b: &Frontiers) -> LoroResult<DiffBatch>
pub fn diff(&self, a: &Frontiers, b: &Frontiers) -> LoroResult<DiffBatch>
Calculate the diff between two versions so that apply diff on a will make the state same as b.
NOTE: This method will make the doc enter the detached mode.
Sourcepub fn apply_diff(&self, diff: DiffBatch) -> LoroResult<()>
pub fn apply_diff(&self, diff: DiffBatch) -> LoroResult<()>
Apply a diff to the current state.
Sourcepub fn diagnose_size(&self)
pub fn diagnose_size(&self)
This is for debugging purpose. It will travel the whole oplog
pub fn oplog_frontiers(&self) -> Frontiers
pub fn state_frontiers(&self) -> Frontiers
Sourcepub fn cmp_with_frontiers(&self, other: &Frontiers) -> Ordering
pub fn cmp_with_frontiers(&self, other: &Frontiers) -> Ordering
- Ordering::Less means self is less than target or parallel
- Ordering::Equal means versions equal
- Ordering::Greater means self’s version is greater than target
Sourcepub fn cmp_frontiers(
&self,
a: &Frontiers,
b: &Frontiers,
) -> Result<Option<Ordering>, FrontiersNotIncluded>
pub fn cmp_frontiers( &self, a: &Frontiers, b: &Frontiers, ) -> Result<Option<Ordering>, FrontiersNotIncluded>
Compare two Frontiers causally.
If one of the Frontiers are not included, it will return FrontiersNotIncluded.
pub fn subscribe_root(&self, callback: Subscriber) -> Subscription
pub fn subscribe( &self, container_id: &ContainerID, callback: Subscriber, ) -> Subscription
pub fn subscribe_local_update( &self, callback: LocalUpdateCallback, ) -> Subscription
pub fn import_batch(&self, bytes: &[Vec<u8>]) -> LoroResult<ImportStatus>
Sourcepub fn get_deep_value(&self) -> LoroValue
pub fn get_deep_value(&self) -> LoroValue
Get deep value of the document.
Sourcepub fn get_deep_value_with_id(&self) -> LoroValue
pub fn get_deep_value_with_id(&self) -> LoroValue
Get deep value of the document with container id
pub fn checkout_to_latest(&self)
Sourcepub fn checkout(&self, frontiers: &Frontiers) -> LoroResult<()>
pub fn checkout(&self, frontiers: &Frontiers) -> LoroResult<()>
Checkout DocState to a specific version.
This will make the current DocState detached from the latest version of OpLog. Any further import will not be reflected on the DocState, until user call LoroDoc::attach()
pub fn vv_to_frontiers(&self, vv: &VersionVector) -> Frontiers
pub fn frontiers_to_vv(&self, frontiers: &Frontiers) -> Option<VersionVector>
Sourcepub fn merge(&self, other: &Self) -> LoroResult<ImportStatus>
pub fn merge(&self, other: &Self) -> LoroResult<ImportStatus>
Import ops from other doc.
After a.merge(b)
and b.merge(a)
, a
and b
will have the same content if they are in attached mode.
pub fn len_ops(&self) -> usize
pub fn len_changes(&self) -> usize
pub fn config(&self) -> &Configure
Sourcepub fn check_state_diff_calc_consistency_slow(&self)
pub fn check_state_diff_calc_consistency_slow(&self)
This method compare the consistency between the current doc state and the state calculated by diff calculator from beginning.
Panic when it’s not consistent
pub fn log_estimated_size(&self)
pub fn query_pos( &self, pos: &Cursor, ) -> Result<PosQueryResult, CannotFindRelativePosition>
Sourcepub fn free_history_cache(&self)
pub fn free_history_cache(&self)
Free the history cache that is used for making checkout faster.
If you use checkout that switching to an old/concurrent version, the history cache will be built. You can free it by calling this method.
Sourcepub fn free_diff_calculator(&self)
pub fn free_diff_calculator(&self)
Free the cached diff calculator that is used for checkout.
Sourcepub fn has_history_cache(&self) -> bool
pub fn has_history_cache(&self) -> bool
If you use checkout that switching to an old/concurrent version, the history cache will be built.
You can free it by calling free_history_cache
.
Sourcepub fn compact_change_store(&self)
pub fn compact_change_store(&self)
Encoded all ops and history cache to bytes and store them in the kv store.
The parsed ops will be dropped
Sourcepub fn analyze(&self) -> DocAnalysis
pub fn analyze(&self) -> DocAnalysis
Analyze the container info of the doc
This is used for development and debugging
Sourcepub fn get_path_to_container(
&self,
id: &ContainerID,
) -> Option<Vec<(ContainerID, Index)>>
pub fn get_path_to_container( &self, id: &ContainerID, ) -> Option<Vec<(ContainerID, Index)>>
Get the path from the root to the container
pub fn export(&self, mode: ExportMode<'_>) -> Result<Vec<u8>, LoroEncodeError>
Sourcepub fn shallow_since_vv(&self) -> ImVersionVector
pub fn shallow_since_vv(&self) -> ImVersionVector
The doc only contains the history since the shallow history start version vector.
This is empty if the doc is not shallow.
The ops included by the shallow history start version vector are not in the doc.
pub fn shallow_since_frontiers(&self) -> Frontiers
Sourcepub fn is_shallow(&self) -> bool
pub fn is_shallow(&self) -> bool
Check if the doc contains the full history.
Sourcepub fn get_pending_txn_len(&self) -> usize
pub fn get_pending_txn_len(&self) -> usize
Get the number of operations in the pending transaction.
The pending transaction is the one that is not committed yet. It will be committed
after calling doc.commit()
, doc.export(mode)
or doc.checkout(version)
.
pub fn find_id_spans_between( &self, from: &Frontiers, to: &Frontiers, ) -> VersionVectorDiff
Sourcepub fn subscribe_first_commit_from_peer(
&self,
callback: FirstCommitFromPeerCallback,
) -> Subscription
pub fn subscribe_first_commit_from_peer( &self, callback: FirstCommitFromPeerCallback, ) -> Subscription
Subscribe to the first commit from a peer. Operations performed on the LoroDoc
within this callback
will be merged into the current commit.
This is useful for managing the relationship between PeerID
and user information.
For example, you could store user names in a LoroMap
using PeerID
as the key and the UserID
as the value.
Sourcepub fn subscribe_pre_commit(&self, callback: PreCommitCallback) -> Subscription
pub fn subscribe_pre_commit(&self, callback: PreCommitCallback) -> Subscription
Subscribe to the pre-commit event.
The callback will be called when the changes are committed but not yet applied to the OpLog.
You can modify the commit message and timestamp in the callback by [ChangeModifier
].
Source§impl LoroDoc
impl LoroDoc
pub fn travel_change_ancestors( &self, ids: &[ID], f: &mut dyn FnMut(ChangeMeta) -> ControlFlow<()>, ) -> Result<(), ChangeTravelError>
pub fn get_changed_containers_in( &self, id: ID, len: usize, ) -> FxHashSet<ContainerID>
pub fn delete_root_container(&self, cid: ContainerID)
pub fn set_hide_empty_root_containers(&self, hide: bool)
Source§impl LoroDoc
impl LoroDoc
Sourcepub fn subscribe_peer_id_change(
&self,
callback: PeerIdUpdateCallback,
) -> Subscription
pub fn subscribe_peer_id_change( &self, callback: PeerIdUpdateCallback, ) -> Subscription
Subscribe to the changes of the peer id.
Source§impl LoroDoc
impl LoroDoc
Sourcepub fn txn(&self) -> Result<Transaction, LoroError>
pub fn txn(&self) -> Result<Transaction, LoroError>
Sourcepub fn txn_with_origin(&self, origin: &str) -> Result<Transaction, LoroError>
pub fn txn_with_origin(&self, origin: &str) -> Result<Transaction, LoroError>
Create a new transaction with specified origin.
The origin will be propagated to the events. There can only be one active transaction at a time for a LoroDoc.
pub fn start_auto_commit(&self)
pub fn renew_txn_if_auto_commit(&self, options: Option<CommitOptions>)
Trait Implementations§
Auto Trait Implementations§
impl Freeze for LoroDoc
impl RefUnwindSafe for LoroDoc
impl Send for LoroDoc
impl Sync for LoroDoc
impl Unpin for LoroDoc
impl UnwindSafe for LoroDoc
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the foreground set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red()
and
green()
, which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg()
:
use yansi::{Paint, Color};
painted.fg(Color::White);
Set foreground color to white using white()
.
use yansi::Paint;
painted.white();
Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the background set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red()
and
on_green()
, which have the same functionality but
are pithier.
§Example
Set background color to red using fg()
:
use yansi::{Paint, Color};
painted.bg(Color::Red);
Set background color to red using on_red()
.
use yansi::Paint;
painted.on_red();
Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute
value
.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold()
and
underline()
, which have the same functionality
but are pithier.
§Example
Make text bold using attr()
:
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);
Make text bold using using bold()
.
use yansi::Paint;
painted.bold();
Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi
Quirk
value
.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask()
and
wrap()
, which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk()
:
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);
Enable wrapping using wrap()
.
use yansi::Paint;
painted.wrap();
Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition
value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted
only when both stdout
and stderr
are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);