Skip to content

Tinta is a magical console output tool with support for printing in beautiful colors and with rich formatting, like bold and underline, using static, chain-able methods. It's so pretty, it's almost like a unicorn!

License

Notifications You must be signed in to change notification settings

brandonscript/tinta

Repository files navigation

Tinta

Tinta Logo

Tinta is a magical console output tool with support for printing in beautiful colors and with rich formatting, like bold and underline, using static, chain-able methods. It's so pretty, it's almost like a unicorn!

version GitHub Actions Badge Codacy Badge PyPI - Python Version MIT License Contributor Covenant

Features and Tinta Basics

Tinta takes a statically typed approach to handling rich-color console output.

In the past you might have fiddled with ANSI colors codes, or passed strings to a generic class, only to discover you typo'd one of them! (Yes, we've all been there).

But with Tinta, you can create your own colors.ini file, which dynamically generates builder pattern methods for Tinta. If you add a color for wine to your colors file, you can then use:

from tinta import Tinta
Tinta.load_colors('colors.ini')
Tinta().wine('sip')

You can make a really simple drop-in print() replacement:

Tinta('Our neural pathways have become accustomed '\
      'to your sensory input patterns.').print()

Or you can create a variable to make things easier to read (or use control flows):

from tinta import Tinta

children = True

t = Tinta().mint('Fate.')
t.dark_gray('It protects')
t.underline().red('fools')

if children:
    t.normal().pink('little children')
else:
    t.normal().yellow('spotted cats')

t.dark_gray(', and ships named')
t.mint("Enterprise.").print()

OK, neat, so how is that like unicorns?

Glad you asked! Here are some pretty pictures:

Unicorns


Starbase

Installation and Getting Started

Install Tinta

pip install tinta

(Or visit https://pypi.org/project/tinta/)

Add Tinta to your project

from tinta import Tinta

Tinta('Elementary, my dear!').print()

Create a colors.ini file

An example colors.ini file might look like:

# A list of ansi colors for your console.
green: 35
red: 1
blue: 32
yellow: 214

Or modify the Tinta colors.ini from here.

You can configure a path to your colors.ini file. This path can be relative, or absolute; the best way to make a path is using pathlib.Path(). Tinta will try and find the file in the current working directory, or you can specify a path:

from pathlib import Path
from tinta import Tinta
Tinta.load_colors(Path().cwd() / 'config/colors.ini')

Customizing your colors

You can use Tinta.discover() to discover what colors are available on your console.

Tinta.discover()
# or to show the colors in the background
Tinta.discover(background=True)

Tinta.discover() output, a set of ANSI color-coded numbers in the terminal

Tinta Basics

from tinta import Tinta

Tinta('Unicorns are soft').print()
# prints: Unicorns are soft in plain text

Tinta('Unicorns are soft').pink().print()
# prints: Unicorns are soft in pink

Tinta('Unicorns are soft').pink().bold().print()
# prints: Unicorns are soft in bold pink

# You can chain as many methods as you want, and you can instantiate a single Tinta object
t = Tinta()
t.pink('Unicorns are soft, and').bold('very').normal('kind.')
t.print()
Tinta().pink('Unicorns are soft, and').bold('very').normal('kind.').print()
# prints: Unicorns are soft, and very kind.
#         [--------pink--------][bold][normal]

# Notice how spaces are preserved between segments?
# You can change this with the sep arg:
Tinta().pink('Unicorns are soft, and', sep="").bold('very', sep="").normal('kind.').print()
# prints: Unicorns are soft,andvery kind.
# or...
Tinta().pink('Unicorns are soft, and').bold('very').normal('kind.').print(sep="")
# prints: Unicorns are soft, andverykind.

# Tinta will also try and automatically fix common punctuation issues that can occur when segments are joined together:
Tinta().pink('Unicorns are soft, and').purple(", you know,").bold('very').normal(', very, kind.').print()
# With smart fixing disabled, this would normally print:
# > Unicorns are soft, and , you know, very , very, kind.

# But with smart fixing enabled, it prints correctly:
# > Unicorns are soft, and, you know, very, very, kind.

# This is turned on by default, but you can disable this by setting TINTA_SMART_FIX_PUNCTUATION to `false` in your environment.

You can run the examples in the examples/ directory to see more:

# check out the repo
git clone https://github.com/brandonscript/tinta.git
cd tinta
python examples/basic_example.py

API Reference

Tinta (+ color methods)

Dynamic methods

These methods are loaded dynamically from your colors.ini file:

Tinta().green()
Tinta().red()
Tinta().blue()
Tinta().wine()
Tinta().my_color()
# etc.

A note on linters like Pylance or pylint: these methods are dynamically generated, so they won't be recognized by your linter as built-in methods. Until Python natively supports type definitions for dynamically generated code, you may have to suppress these warnings:

# pyright: reportGeneralTypeIssues=false
Tinta().green() # or
# pylint: disable=no-member
Tinta().green()

Tinta().green() # type: ignore

If this is frustrating, you can always use the Tinta.tint(<color>) methods, which are not dynamically generated.

Common Args

All "add" methods (each color and style method, Tinta(), push(), and tint) take the following common args:

  • s (str) – A sequence of one or more text strings, to be joined together.
  • sep (str) – Used to join segment strings. Defaults to ' '.

    Note: sep behavior has been changed in v0.1.7b5-post1 - if passing a sep argument in print(), it will overwrite any segment's individual sep argument.

For example:

Tinta('A set', 'of strings', 'joined', 'with', 'semicolons', sep=';').print()
~ » A set;of strings;joined;with;semicolons

(or)

Tinta('A set', 'of strings', 'joined', 'with', 'double spaces').print(sep='  ')
~ » A set  of strings  joined  with  double spaces

Attributes

All Tinta and dynamic color methods will make available the following attributes:

  • color (str) — A color string or ANSI color code (int), e.g. 'white' or 42.
  • style (str) — A style string, e.g. 'bold', 'dim', 'underline'. Multiple styles are joined with a +.
  • parts (list) — A list of Tinta.Part segments, which each have a fmt, pln, and esc attribute.
  • parts_plaintext (list) — A list of unstyled text segments.

Built-in Methods

See below for detailed usage and arguments.

(Note: breaking changes in v0.1.7b5-post1 - several methods have been renamed for better semantics).

  • print() – Prints to the console.
  • to_str() -> str – Returns a joined text string.
  • discover() – Prints a list of available colors to the console.

Remember, all of the following methods return the current Tinta instance -> self so you can chain styles together:

  • () or push() – Adds another segment using the previous style. Replaces add().

  • pop() – Removes the last segment. This is useful if you want to remove a segment that was added with push().

  • tint() – Behaves like .push(), but adds segments using the specified color string or ANSI code. Replaces code().

  • nl() – Appends the contents preceded by a newline char (\n). Renamed from line().

  • clear() – Clears all styling for the next segment so it uses terminal default styling. Replaces reset().

  • b() or bold() – Adds a bold segment.

  • _() or u() or underline() – Adds an underlined segment.

  • dim() – Adds a darker, dimmed segment.

  • normal() – Resets the style, but retains any active color.

print()

Prints to the console. Probably the most important method, because if you don't print, you don't see anything at all! A good first step in troubleshooting is checking that you remembered to print() (ask me how I know...)

This supports all the built-in Python 3 print() methods, too (sep, end, file, flush), as well as:

  • sep (str) – Used to join segment strings. Defaults to ' '.
  • plaintext (bool) – Returns a compiled plaintext string
  • escape_ansi (bool) – If True, escapes ANSI codes with a double \. Defaults to False.
  • fix_punctuation (bool) – If True, fixes common punctuation issues. Defaults to True, or the value of 'env::TINTA_SMART_FIX_PUNCTUATION'. and
  • s* (str) – You can also pass any arbitrary sequence of strings to print() to push additional segments.
# Prints in plaintext
Tinta().purple("Is it a bird?").print("No, maybe it's a...", plaintext=True)

# Always prints, even if 'env::TINTA_STEALTH' is set)
Tinta().green('Plane?').print(force=True)

It's also important to note that print() doesn't make a variable unusable, but it will reset and remove all styles and previous segments. This means you can do:

t = Tinta()

t.blue('A cloud').print()
t.green('An old, wise, and very small alien').print()

to_str()

Previously text()

Constructs the string that would be sent to print(), but returns it instead of printing it. Accepts all the same arguments as print() except file and flush.

() or push()

Previously add()

Sometimes you want the convenience of readability without changing styles, or you might want to use control flow to set a variable. For these, you can directly chain any Tinta object via its __call__ method, or via push():

t = Tinta().gray('I am a bear')
if you_love_bears:
    t.pink('and I love bears!')
else:
    t('but I am sad.')
    # or
    t.push('but I am sad.')
t.print()

Tinta().brown('I')('am a brown bear').black(', and I am a')('black bear.').print()

nl()

Adds a text segment preceded by a newline.

Tinta('A cat').line('scratches').print()
# A cat
# scratches

tint()

Sometimes you might want to use a color by string name, or one that wasn't defined in your colors.ini. For that, you can use tint().

Note: some of this functionality was previously in code(), which is now combined into tint().

Just set the color kwarg to specify an ANSI color code or string name:

Tinta().tint('A bear who knows all the answers', color=42).print()
Tinta().tint('A brown bear', color='brown').print()

If you don't pass a color kwarg, the first argument will be used as the color:

Tinta().tint(42, 'A bear who knows all the answers').print()
Tinta().tint('brown', 'A brown bear').print()

Environment Variables

Sometimes it's useful to globally configure Tinta on a system where you might want it to behave differently, without changing your source code. If these Environment variables are present on the system, they will be considered True.

TINTA_STEALTH – Disables console output globally

TINTA_PLAINTEXT – Disables rich console output, only printing plain text.

TINTA_SEPARATOR – Changes the default separator (' ') to this value.

TINTA_SMART_FIX_PUNCTUATION – Controls smart punctuation fixing (default: true)

Running Tests

To run tests, run the following command:

pip install pytest
python -m pytest -v

Contributing

Contributions are welcome! Please send in a PR with a clear explanation of what you're adding and why, and where applicable, add tests to validate. Please read our code of conduct before contributing.

Acknowledgements

Special thanks to @katherinecodes for readme.so, @jessicaspacekat for rikeripsum.com, and ansicolors.

License

Tinta is licensed under the MIT License. If you use this software, you must also agree under the terms of the Hippocratic License 3.0 to not use this software in a way that directly or indirectly causes harm. You can find the full text of the license at https://firstdonoharm.dev.

About

Tinta is a magical console output tool with support for printing in beautiful colors and with rich formatting, like bold and underline, using static, chain-able methods. It's so pretty, it's almost like a unicorn!

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages