【问题标题】:How to colourise user input in Python?如何在 Python 中为用户输入着色?
【发布时间】:2021-07-04 18:51:49
【问题描述】:

我正在创建一个命令行计算器工具,我想让它在用户键入时格式化用户输入,类似于 Fish 和 Powershell 所做的 (screenshots)。

目前,我能想到的唯一简单方法是一次获取一个字符,然后将格式化的行重新打印到屏幕上。

# This code is probably very dodgy, 
# it's just to give you an idea what I'm thinking
# Use external getch module to get input without echoing to screen
from getch import getch 
inp = ""
while True:
    char = getch()
    if char == '\n': break
    if char == '\b': inp = inp[:-1]
    else: inp += char
    # Print with carriage return so that next input overwrites it
    print(colourFormatInput(inp) + '\r') 
# Outside loop: process input and devliver results

虽然这在技术上可行,但我觉得这需要大量的手动操作,而且如果我想添加诸如使用箭头键移动光标位置之类的功能只会变得更加复杂。

有没有一种简单的方法来获得这种功能而无需自己编写所有代码?

【问题讨论】:

  • 这能回答你的问题吗? How to print colored text to the terminal?
  • 你试过rich吗?这可能对你有好处github.com/willmcgugan/rich
  • 可悲的是,看起来这两个都是用于打印输出,而不是格式化输入,所以虽然它们可以帮助格式化,但它们对于解决格式化用户遇到的问题并没有多大帮助输入时输入。

标签: python input


【解决方案1】:

我使用库colorama

import colorama
import sys


def hook(tp, *args):
    if tp is KeyboardInterrupt:
        print(colorama.Fore.RESET)
        exit()


def colored_input(text: str, color):
    sys.excepthook = hook
    inp = input(text + color)
    print(colorama.Fore.RESET, end="", flush=True)
    sys.excepthook = sys.__excepthook__
    return inp


name = colored_input("What's your name? ", colorama.Fore.RED)
age = colored_input("What's your age? ", colorama.Fore.YELLOW)

print(f"Nice to meet you {name}({age})")

我使用sys.excepthook 捕捉KeyboardInterrupt,这样我可以在用户键入CTRL+C 时重置颜色,然后我将原来的异常钩子设置回来(sys.__excepthook__

【讨论】:

  • 因此,如果输入是单色,则此方法有效,但不可能得到如下内容:[white] 10 [cyan] + [yellow] x [cyan] = [white] 20,因为他们输入了表达式
  • @HDSQ 很抱歉造成误会,你能解释一下你的意思吗?
  • 给我一分钟,我会快速截几张截图
  • 链接到我想要实现的截图:imgur.com/a/Z2nafYn
  • @HDSQ 你的意思是你可以在打字的时候设置颜色?嗯好的
【解决方案2】:

您可以通过prompt_toolkit 做到这一点

如果您需要,这里是文档:

您可以通过示例中给出的以下内容将语法突出显示添加到输入中:

添加语法高亮就像添加词法分析器一样简单。所有的 Pygments 词法分析器都可以在将它们包装在 PygmentsLexer 中之后使用。也可以通过实现 Lexer 抽象基类来创建自定义词法分析器。

from pygments.lexers.html import HtmlLexer
from prompt_toolkit.shortcuts import prompt
from prompt_toolkit.lexers import PygmentsLexer

text = prompt('Enter HTML: ', lexer=PygmentsLexer(HtmlLexer))
print('You said: %s' % text)

以与上述相同的方式,您可以创建自定义prompt_toolkit.lexers.Lexer 用于计算器突出显示,就像以下示例一样。在这里,我创建了一个自定义帮助器类:

from typing import Callable
from prompt_toolkit.document import Document
from prompt_toolkit.formatted_text.base import StyleAndTextTuples
from prompt_toolkit.formatted_text import FormattedText
from prompt_toolkit.shortcuts import prompt
import prompt_toolkit.lexers
import re

class CustomRegexLexer(prompt_toolkit.lexers.Lexer):
    def __init__(self, regex_mapping):
        super().__init__()
        self.regex_mapping = regex_mapping

    def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
        def lex(_: int):
            line = document.text
            tokens = []
            while len(line) != 0:
                for pattern, style_string in self.regex_mapping.items():
                    match: re.Match = pattern.search(line)

                    if not match:
                        continue
                    else:
                        # print(f"found_match: {match}")
                        pass
                    match_string = line[:match.span()[1]]
                    line = line[match.span()[1]:]
                    tokens.append((style_string, match_string))
                    break
            return tokens
        return lex

现在实现了上述帮助类,我们可以创建我们的正则表达式模式及其各自的样式,要了解更多关于样式字符串的信息,请访问this page

# Making regex for different operators. Make sure you add `^` anchor
# to the start of all the patterns
operators_allowed = ["+", "-", "/", "*", "(", ")", "=", "^"]
operators = re.compile("^["+''.join([f"\\{x}" for x in operators_allowed])+"]")
numbers = re.compile(r"^\d+(\.\d+)?")
text = re.compile(r"^.")


regex_mapping = {
    operators: "#ff70e5",  # Change colors according to your requirement
    numbers: "#ffa500",
    text: "#2ef5ff",
}

MyCalculatorLexer = CustomRegexLexer(regex_mapping)

创建词法分析器后,您现在可以在函数提示符中使用词法分析器:

text = prompt("Enter Equation: ", lexer=MyCalculatorLexer)

# Or

def input_maths(message):
    return prompt(message, lexer=MyCalculatorLexer)

text = input_maths("Enter Equation: ")

这是一些示例输出:

现在一切正常。也请查看prompt_toolkit,您可以 创建大量自定义内容,如gallery

所示

【讨论】:

  • 我已经纠正了一个错误,请检查它是否有效,不幸的是在纠正之前它崩溃了
  • 收到错误type object 'CalculatorLexer' has no attribute 'lex_document'
  • 请等到我的电脑重新启动。不幸的是,我现在把它撞了两次
  • 我会尽快纠正错误,我自己现在也面临问题:stackoverflow.com/questions/68242016/…
  • 看起来这可能是 Regex 词法分析器本身的问题,因为使用 python -m pygments -x -l lexer.py:CalculatorLexer temp.txt 运行它,其中 temp.txt 是一些随机数学输入会导致它冻结。
【解决方案3】:

另一个例子:


CGREEN = '\33[32m'
CYELLOW = '\33[33m'
CBLUE = '\33[34m'
CVIOLET = '\33[35m'
CBEIGE = '\33[36m'
CWHITE = '\33[37m'
CGREY = '\33[90m'
CRED = '\033[91m'
CYELLOW = '\33[33m'
CYELLOW2 = '\33[93m'
CEND = '\033[0m'

print(CGREEN + "This is green text" + CEND)
print(CYELLOW + "This is yellow text" + CEND)

# Another interesting example (courtesy: https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html)

for i in range(0, 16):
    for j in range(0, 16):
        code = str(i * 16 + j)
        colorCode = u"\u001b[48;5;" + code + "m"
        print(colorCode + " Color {} ".format(code) + CEND)

【讨论】:

  • 这只是纯彩色打印文本,但此答案未显示任何与 OP 要求的输入相关的内容,并且不支持跨平台代码的彩色文本,您也没有给出任何原因是正确答案。就像没有人要求一个以所有颜色打印文本的程序一样。如果您不明白,请重新阅读问题
猜你喜欢
  • 2023-01-25
  • 2021-08-18
  • 2021-12-03
  • 2017-07-07
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多