@parischap/pretty-print
Version:
A functional library to pretty-print and treeify objects
129 lines • 5.01 kB
JavaScript
/**
* This module implements a type that defines a specific stringification process for certain values
* (the normal stringification process is by-passed, hence its name). For instance, you may prefer
* printing a Date as a string rather than as an object with all its technical properties.
*
* With the make function, you can define your own instances if the provided ones don't suit your
* needs.
*/
import { MFunction, MInspectable, MPipeable, MRecord, MRegExp, MTypes } from '@parischap/effect-lib';
import { ASText } from '@parischap/ansi-styles';
import { Array, Equal, flow, Function, Hash, Option, pipe, Predicate, String, Struct } from 'effect';
import * as PPStringifiedValue from './StringifiedValue.js';
import * as PPValue from './Value.js';
/**
* Module tag
*
* @category Models
*/
export const moduleTag = '@parischap/pretty-print/ByPasser/';
const _TypeId = /*#__PURE__*/Symbol.for(moduleTag);
/**
* Type guard
*
* @category Guards
*/
export const has = u => Predicate.hasProperty(u, _TypeId);
/**
* Equivalence
*
* @category Equivalences
*/
export const equivalence = (self, that) => that.id === self.id;
/** Base */
const _TypeIdHash = /*#__PURE__*/Hash.hash(_TypeId);
const base = {
[_TypeId]: _TypeId,
[Equal.symbol](that) {
return has(that) && equivalence(this, that);
},
[Hash.symbol]() {
return pipe(this.id, Hash.hash, Hash.combine(_TypeIdHash), Hash.cached(this));
},
[MInspectable.IdSymbol]() {
return this.id;
},
... /*#__PURE__*/MInspectable.BaseProto(moduleTag),
...MPipeable.BaseProto
};
/**
* Constructor
*
* @category Constructors
*/
export const make = ({
id,
action
}) => Object.assign(MFunction.clone(action), {
id,
...base
});
/**
* Returns the `id` property of `self`
*
* @category Destructors
*/
export const id = /*#__PURE__*/Struct.get('id');
/**
* ByPasser instance that does not bypass any value
*
* @category Instances
*/
export const empty = /*#__PURE__*/make({
id: 'Empty',
action: () => () => Option.none()
});
/**
* ByPasser instance that has the following behavior:
*
* - For any function: a some of the function name surrounded by the function delimiters and the
* message delimiters. If the function name is an empty string, `anonymous` is used instead.
* - For any other value: returns a `none`
*
* @category Instances
*/
export const functionToName = /*#__PURE__*/make({
id: 'FunctionToName',
action: ({
valueBasedStylerConstructor,
markShowerConstructor
}) => {
const messageTextFormatter = valueBasedStylerConstructor('Message');
const functionNameStartDelimiterMarkShower = markShowerConstructor('FunctionNameStartDelimiter');
const functionNameEndDelimiterMarkShower = markShowerConstructor('FunctionNameEndDelimiter');
const messageStartDelimiterMarkShower = markShowerConstructor('MessageStartDelimiter');
const messageEndDelimiterMarkShower = markShowerConstructor('MessageEndDelimiter');
return value => pipe(value, Option.liftPredicate(PPValue.isFunction), Option.map(flow(PPValue.content, MFunction.name, Option.liftPredicate(String.isNonEmpty), Option.getOrElse(Function.constant('anonymous')), messageTextFormatter(value), ASText.surround(functionNameStartDelimiterMarkShower(value), functionNameEndDelimiterMarkShower(value)), ASText.surround(messageStartDelimiterMarkShower(value), messageEndDelimiterMarkShower(value)), PPStringifiedValue.fromText)));
}
});
/**
* ByPasser instance that has the following behavior:
*
* - For any non-primitive value which is not an iterable or a function : tries to call the toString
* method (only if it is different from Object.prototype.toString). Returns a `some` of the result
* if successful. Returns a `none` otherwise. Calling the .toString method on an Iterable will not
* be as efficient as using the `FromValueIterable` or `FromKeyValueIterable` property sources.
* Calling the .toString method on a function will not work properly.
* - For any other value: returns a `none`
*
* @category Instances
*/
export const objectToString = /*#__PURE__*/make({
id: 'ObjectToString',
action: ({
valueBasedStylerConstructor
}) => {
const toStringedObjectTextFormatter = valueBasedStylerConstructor('ToStringedObject');
return value => {
const inContextToStringedObjectTextFormatter = toStringedObjectTextFormatter(value);
return pipe(value.content, Option.liftPredicate(MTypes.isNonPrimitive), Option.filter(Predicate.not(Predicate.or(MTypes.isIterable, MTypes.isFunction))), Option.flatMap(flow(MRecord.tryZeroParamStringFunction({
functionName: 'toString',
/* eslint-disable-next-line @typescript-eslint/unbound-method */
exception: Object.prototype.toString
}))), Option.map(flow(
// split resets RegExp.prototype.lastIndex after executing
String.split(MRegExp.globalLineBreak), Array.map((s, _i) => inContextToStringedObjectTextFormatter(s)))));
};
}
});
//# sourceMappingURL=ByPasser.js.map