muesli4 / table-layout

Layout data in grids and pretty tables. Provides a lot of tools to get the cell formatting right (positional alignment, alignment on specific characters and limiting of cell width)..
BSD 3-Clause "New" or "Revised" License
37 stars 11 forks source link

measureAlignment can only match first character matching predicate #32

Closed Xitian9 closed 2 years ago

Xitian9 commented 2 years ago

Based on the way measureAlignment :: Cell a => (Char -> Bool) -> a -> AlignInfo is defined and implemented, it will always match the first character within the cell which satisfies the predicate. Unfortunately this is not sufficient for all the cases one might want. You might want to match the first character on the right, or you might want to use a predicate which considers more than characters.

In my case, I want to align on decimal points, but among numbers which might use a mix of commas and periods for decimal separators. Furthermore, they might use the other symbol as a thousands separator. Here's an example of the output I'd like:

$1 005.15
£2,167.00
15.011,18€
¥1,235

I haven't yet figured out what the best approach to this problem is, but measureAlignment is not up to snuff. Clearly the job of marking which of these characters is the decimal point would not be the job of table-layout and would be up to me, but even if I could mark it somehow, measureAlignment couldn't take it into account since it only sees a single character at a time from the left. At the very least, we'd need to generalise the form of the predicate somehow.

Xitian9 commented 2 years ago

Actually, I think this can be accomplished without any changes. I think it just requires a somewhat odd implementation of Cell.

data PointedNumber = PointedNumber String Char String

instance Cell PointedNumber where
  measureAlignment _ (PointedNumber w p d) = AlignInfo (length w) (Just $ length d)

I'll close this issue, but it might be good to have a record of it in case anybody comes across a similar need.

muesli4 commented 1 year ago

This could be implemented but probably needs a bit more thought:

There is also the more general question whether a text input is sufficient enough to get a good output rendered. For example, for scientific output one might want to use the exponent notation but just for numbers that are too big. But getting semantics into input would probably open up a whole new can of worms. But for anyone interested, knock yourself out. :laughing:

Xitian9 commented 1 year ago

I agree that this is probably too specific to be included in anything we provide. But it's a useful trick to keep in mind for specific use cases people may have.

But more generally, the type of measureAlignment :: (Char -> Bool) -> a -> AlignInfo restricts us to only considering single characters sequentially. Would a more general type be more useful?