What $TERM should be utilized in order to enable both 256 colors and mouse movement events within Python's curses module?

When I set the TERM environment variable to 'xterm-1003', I can receive mouse move events, but the color display is not great and curses.can_change_color() returns False.

os.environ['TERM'] = 'xterm-1003'
...
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
...
while True:
    event = screen.getch()
    if event == curses.KEY_MOUSE:
        # Mouse move events are received without needing a click
        _, mx, my, _, _ = curses.getmouse()

If I change the TERM env var to 'xterm-256color', the color palette improves and curses.can_change_color() returns True. However, mouse events are only triggered by clicking a button.

>ls /usr/share/terminfo/x/ 

The terminal info directory reports various available options:

xfce           xterm-256color  xterm-hp      xterm-r5     xterm-xf86-v32   xterm-xfree86
xterm          xterm-88color   xterm-new     xterm-r6     xterm-xf86-v33   xterm-xi
xterm-1002     xterm-8bit      xterm-nic     xterm-sco    xterm-xf86-v333  xterms
xterm-1003     xterm-basic     xterm-noapp   xterm-sun    xterm-xf86-v40
xterm-16color  xterm-bold      xterm-old     xterm-vt220  xterm-xf86-v43
xterm-24       xterm-color     xterm-pcolor  xterm-vt52   xterm-xf86-v44

None of these options seem to satisfy both requirements of curses.can_change_color() being True and receiving mouse move events. Is there a method to achieve both by adjusting the $TERM value or another approach?

Your assistance is greatly appreciated!

Answer №1

If you want to customize your terminal settings, you have the freedom to create your own using tools like infocmp (to display an entry's contents) and tic (to compile an entry). If system permissions are a concern, it will save to $HOME/.terminfo.

To begin, take a look at xterm-1003 and xterm-256color:

> infocmp -x xterm-1003 xterm-256color
comparing xterm-1003 to xterm-256color.
    comparing booleans.
        ccc: F:T.
    comparing numbers.
        colors: 8, 256.
        pairs: 64, 32767.
    comparing strings.
        initc: NULL, '\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\'.
        setab: '...'.
        setaf: '...'.
        setb: '...', NULL.
        setf: '...', NULL.
        XM: '...', NULL.

In essence, you simply need to add the XM functionality to a modified version of xterm-256color.

Here's how:

  1. infocmp -x xterm-256color >foo
  2. Edit foo file to include the XM string
  3. tic -x foo

The "-x" flag is crucial for tic to process the XM capability, which is recognized by ncurses as an additional custom feature in the directory database.

Answer №2

Check out this helpful solution which offers a straightforward approach without causing any system disruptions.

curses.mousemask(curses.REPORT_MOUSE_POSITION)
print('\033[?1003h') # activate mouse tracking using the XTERM API

Make sure to follow the order: first call mousemask(), then execute the print statement.

Answer №3

The issue at hand: Mouse position being reported even without any mouse button being clicked.

This response is meant to complement the previous answer by Thomas Dickey. By following the referenced links and carrying out basic instructions, I successfully pinpointed an XM string that resolved my desired mouse behavior.

My concern with the XM string mentioned in the prior answer was the continuous reporting of mouse position when no mouse button was pressed. My objective was to only receive mouse position updates during a mouse drag event — meaning when a mouse button was actually held down. While constant reporting might be useful for implementing a "mouse hover" feature, it served no purpose for me and simply led to wasted processing cycles in the application's event loop.

To discover the appropriate XM string, I undertook the following steps:

  1. Created a 'foo' file as instructed in the aforementioned answer:
    infocmp -x xterm-256color > foo
  2. Extracted all the XM strings from the content provided in the terminal database link.
  3. Appended one of the XM strings to my version of 'foo' and executed tic -x foo (implementing the new configuration instantly).
  4. Executed my program to observe if the mouse positioning functioned as desired.
  5. If the behavior varied, returned to step 3 to test the next string.

The extracted (commented out) XM strings from the "terminal database" link are displayed below:

#    XM=\E[?9%?%p1%{1}%=%th%el%;,
#    XM=\E[?9%?%p1%{1}%=%th%el%;,
#    xm=\E[M%p3%' '%+%c%p2%'!'%+%c%p1%'!'%+%c,
#    XM=\E[?1000%?%p1%{1}%=%th%el%;,
#    xm=\E[M%?%p4%t%p3%e%{3}%;%'\s'%+%c%p2%'!'%+%c%p1%'!'%+%c,
#    XM=\E[?1001%?%p1%{1}%=%th%el%;,
#    XM=\E[?1002%?%p1%{1}%=%th%el%;,
#    XM=\E[?1003%?%p1%{1}%=%th%el%;,
#    XM=\E[?1005;1000%?%p1%{1}%=%th%el%;,
#    xm=\E[M%?%p4%t3%e%p3%'\s'%+%c%;%p2%'!'%+%c%p1%'!'%+%c,
#    XM=\E[?1006;1000%?%p1%{1}%=%th%el%;,
#    xm=\E[<%i%p3%d;%p1%d;%p2%d;%?%p4%tM%em%;,

The XM string that produced the desired outcome on my Ubuntu 20 system's bash terminal was:

    XM=\E[?1002%?%p1%{1}%=%th%el%;,

I envision doing additional fine-tuning to enable this behavior on other systems once my application is close to distribution-ready.

A potential downside is that this alteration may impact bash behavior overall, not just when my app is operating within a bash terminal. A possibly better approach could involve refraining from modifying the xterm-256color file directly, but rather creating a custom file with a distinct name unlikely to clash with standard files. Subsequently, in my application, setting the TERM environment variable to this unique file before launching curses.

    os.environ['TERM'] = 'mouse-tweaked-xterm-256color'
    curses.wrapper(start_my_app)

Update: The newly generated xterm-256color file via tic was found on my system under ${HOME}/.terminfo/x/. I renamed it and implemented the above code snippet to define TERM within the application.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Python BeautifulSoup for isolating specific tags in XML documents

In my metadata file, the structure is as follows: <?xml version='1.0' encoding='utf-8'?> <package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uuid_id" version="2.0"> <metadata ...

Navigating through xpath in Python Selenium?

a = driver.find_elements_by_xpath("//article[3]/div[3]/div[2]/a[*[local-name()='time']]") for links in a: print (links.text) This code snippet is part of a project I am developing for Instagram using Selenium. It aims to track the mo ...

Grouping data in a numerical column using PySpark

In my PySpark DataFrame df, there is a numerical column with some NaN values: +-------+ |numbers| +-------+ | 142.56| | | |2023.33| | 477.76| | 175.52| |1737.45| | 520.72| | 641.2| | 79.3| | 138.43| +-------+ I am looking to create a new column t ...

Creating a weekly year pivot table in pandas

I'm a beginner with pandas and I need to create pivot tables for each week using data from a csv file that contains records spanning multiple years. I am having trouble figuring out the best way to filter the dataframe by week. Currently, I am doing ...

Optimizing the import of a csv file into pandas with various separators or compression methods

I'm dealing with a variety of csv files stored on s3, some compressed with gzip and others not. Additionally, some use semicolons while others use commas as separators. What would be the most effective approach to detect and load these files? Current ...

What is the specific data type format for dtype(S3) in Python?

Whenever I try to specify a pandas dataframe column for the size argument in a matplotlib scatter plot, I keep running into this error: "Cannot cast array data from dtype('S3') to dtype('float64') according to the rule 'safe&a ...

Performing mathematical operations using matrices that have lists as their data values

I have multiple sets of data arranged in columns within a dataframe, totaling nine lists in all. My objective is to perform matrix operations on every row present across these columns. To illustrate, consider the following operation: O(G) = trace(G*transp ...

While utilizing Selenium and Python, a cookie connected with a cross-site resource at http://yahoo.com/ was established without the inclusion of the `SameSite` attribute

Scraping a website using selenium resulted in the following message appearing in the output, amidst the desired content: [0306/125211.693:INFO:CONSOLE(0)] "A cookie associated with a cross-site resource at http://yahoo.com/ was set without the `SameSite` a ...

What is the process for starting a Dash App that is contained within a package that has already been installed?

In the process of developing a package, I have structured it with a module containing functions (fed3live.py) and another with a Dash App (fed3_app.py). Here is how the package is organized: fed3live/ ├─__init__.py ├─fed3live/ │ └─fed3live.py ...

Unable to interact with an input field in Selenium due to it not being concealed within a shadow DOM or iframe

Currently, I am in the process of scraping data from the website . My journey with automation using Selenium has hit a roadblock as I struggle to click on the input field for entering the city name (referred to as "city" in the code). I've already i ...

Modify each alternating element within an array

matrix = np.array([[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]) vector = np.array([0,0,0,0]) To manipulate vectors, you can update every other element using the following code: vector[1::2] = 1 Applying this will result in: np.array([0,1,0,1]) However, w ...

Tips for transforming a pandas dataframe into a dictionary that can be sliced

My pandas data frame df is structured as follows: import pandas as pd data = [[1, 'Jack', 'A'], [1, 'Jamie', 'A'], [1, 'Mo', 'B'], [1, 'Tammy', 'A'], [2, 'JJ', ' ...

Pandas read_csv function encounters a MemoryError issue

I am dealing with a 5GB file named 1.csv and using a pandas script to remove duplicates. However, every time I try to run the script, I encounter a memory error. I attempted chunking the large file, but this approach only allows me to process parts of the ...

Is it feasible to obtain the PyObject reference using the name of a current variable?

Is there a way to access an existing object's reference in embedded Python code? In other words, if an object named 'obj' already exists (created by a script), is it possible to convert it to a PyObject* reference using a function like: PyO ...

Initiating the personalized profile in Chrome to run test version

When attempting to execute the code below, I keep encountering a SessionNotCreatedException error related to Driver. Does anyone have any insights on how to indicate a ChromeProfile while utilizing Chrome for testing? Error Code: Exception has occurred: ...

Is there a way to efficiently download a large number of images (70,000) from URLs while adhering to restrictions on simultaneous downloads

I'm feeling a bit lost here. I have this csv file containing two columns: name and picture URL. My goal is to bulk download the 70k images from the file and save them in a folder, renaming each image with the corresponding name from the first column. ...

What is the process for removing an element from a PyListObject using the `pop`

If I have a PyListObject and need to add a PyObject, I would typically use the PyList_Append API as detailed in the List Objects C-API. However, in my scenario, I require removing an element from the same PyListObject (similar to my_list.pop() in Python). ...

selenium.common.exceptions.InvalidArgumentException: Error: the specified argument is not valid - incorrect locator provided

Hey there, I've been working on creating a bot using selenium and encountered an issue with the send keys function. Despite trying for hours, I can't seem to figure out how to make it work. If anyone has any insights or solutions, I would greatly ...

Pressing the button only seems to be effective if a time.sleep function is included in the

click() method in python(selenium) seems to require the use of time.sleep() in order to work properly. The main script already includes an implicit wait at the beginning, so it's puzzling why this additional wait is needed. Can anyone offer insight in ...

Separate the dictionaries extracted from API data into individual columns

Starting off, I must admit that I am quite the novice in this field. So, any specific and detailed advice or guidance would be greatly appreciated. I've managed to pull data from Canvas API using the code snippet below: result = requests.get('h ...