-
Notifications
You must be signed in to change notification settings - Fork 444
Description
Feature Request: Character-level replacement for custom symbols
Problem
The current custom_symbols feature is designed to replace entire variable names with a LaTeX friendly string. In some instances it's desirable to swap out individual characters within a variable name. The existing custom_symbols implementation can achieve this, but it can only swap one matching string:
So, for example, if I wanted to introduce parenthesis into a variable by mapping LB and RB to the left and right parenthesis as below:
handcalcs.set_option("custom_symbols", {'LB': '(','RB': ')'})
This would not yield the desired result:
myvarLB1RB would map to myvar(1RB instead of the desired myvar(1)
This occurs because there's a break statement in the swap_custom_symbols method, which prevents subsequent matches being actioned. This is evidently by design, as - if the user is intending only to match whole 'words', rather than a subset of characters within the word - then the variables could quickly become scrambled if multiple matching substrings were found in the custom_symbols list. For example, if the user entered the following:
custom_symbols = { "V_": "V_{", "dot": "\\cdot" "V_dot": "\\dot{V}", }
Then a variable named V_dot would incorrectly be parsed to V_{dot with the first match, and then V_{\\cdot with the second match. The third (desired) string would never match, as - by the time it's reached - the input variable has been scrambled. Note that this risk already exists in the current implementation.
Proposed Solution
- Restrict the existing
swap_custom_symbolsto only match and swap whole-word matches (currently there's a risk of unintended scrambling, as described above). - Add a new
swap_custom_charactersfunction that performs character-level replacement without thebreakstatement, allowing multiple replacements in a single variable name. Having both methods gives the user control over whether to match entire words, or individual characters, increasing flexibility, and reducing the potential for unintended behaviors.
Implementation
I have successfully implemented this feature locally with minimal changes:
- New
swap_custom_charactersfunction (similar to existingswap_custom_symbols) - Added to processing pipeline at the end to avoid conflicts (i.e. the characters swaps are made after all other functions have been performed, so as to avoid conflicting with other existing behaviors).
- New config option
custom_characters - Maintains full backward compatibility
Use Case
This enables clean mathematical notation, utilising parenthesis, commas, and other restricted characters like.
In my current implementation, I've mapped the valid python characters with UniCodes 718, 719, and 716 to the left and right parenthesis, and the comma, respectively, so that I can generate LaTeX representations as below:
handcalcs.set_option("custom_characters", {'ˎ': '(','ˏ': ')', 'ˌ': ','})
-
phi_1ˎ3ˌ2ˏ→$φ_{1(3,2)}$ -
E_c1ˎ2ˏ→$E_{c1(2)}$
As a structural engineer, you'll perhaps appreciate these symbols; the first is the creep coefficient and the second is the concrete modulus used for tracking the response of element 1 (the precast deck panels) from time index 2 to 3 in a stepwise time-dependent analysis of a composite prestressed concrete bridge girder.
I appreciate that these could have been mapped more simply with the current implementation, but I've found accurately matching the notation to reference texts really helps with avoiding errors! Plus it appeals to my OCD, obviously! haha
If you're interested I'd be happy to provide the implementation details or create a pull request, though as described above it's really just a duplication of the existing swap_custom_symbols functionality, only without a break.