This one uses a fixed-width for field 1 of the table including the . leaders.
Field 2 is flexible but must begin with ‘Working’ or ‘Meeting’.
-Chris
Make Two Column Table with . Leader (Perl) v1.00.kmmacros (7.3 KB)
This one uses a fixed-width for field 1 of the table including the . leaders.
Field 2 is flexible but must begin with ‘Working’ or ‘Meeting’.
-Chris
Make Two Column Table with . Leader (Perl) v1.00.kmmacros (7.3 KB)
If you can accept having SPACE filled text, then the simple bash column
command will do.
But if you want exactly what you have posted, then you will need a couple of RegEx Search/Replace Actions to replaces the SPACES with dots. Maybe one of the Shell Script gurus will know how to make the bash column
command use a different fill character.
Below is just an example written in response to your request. You will need to use as an example and/or change to meet your workflow automation needs.
Please let us know if it meets your needs.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-~~~ VER: 1.0 2021-02-10 ~~~
Requires: KM 8.2.4+ macOS 10.11 (El Capitan)+
(Macro was written & tested using KM 9.0+ on macOS 10.14.5 (Mojave))
Create Text Table from TAB Delimited Text [Example].kmmacros
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.
Author.@JMichaelTX -- based on script by @ccstone
PURPOSE:
HOW TO USE
MACRO SETUP
REQUIRES:
TAGS: @TextTable @Regex @ShellScript @Example
USER SETTINGS:
ACTION COLOR CODES
==USE AT YOUR OWN RISK==
Depends.
Do you still want the Working and Meeting to line up and let the extra stuff after that trail off to various lengths? If so, just add (.*)
to the end of the regular expression and add the 3rd captured group to the end of the output, i.e.,
#!/usr/bin/python3
import re
import fileinput
entry = re.compile(r'^(.+)(Meeting|Working)(.*)$')
for line in fileinput.input():
m = entry.match(line)
if m:
print(f'{m.group(1):.<21s} {m.group(2)}{m.group(3)}')
That turns
8 - 10am Working, saw video of people with Cat filter on on video
7 - 9am Working
9 - 11am Meeting with people I hate
11 - 11:30am Meeting
11:30am - 12:30pm Meeting
12:30pm - 1pm Working
2 - 5pm Working
into
8 - 10am ............ Working, saw video of people with Cat filter on on video
7 - 9am ............. Working
9 - 11am ............ Meeting with people I hate
11 - 11:30am ........ Meeting
11:30am - 12:30pm ... Meeting
12:30pm - 1pm ....... Working
2 - 5pm ............. Working
If that's not the kind of output you want, the answer will probably be more complicated.
(If you put .*
after Working and Meeting in the second capture group, there's no need for a third group, and the print
line could go back to what it was. I added the third group because I thought it made the code clearer. Now I'm not sure there's any value in it.)
It was a good question and harvested well, not only because it clearly showed:
but also, I think, because it touches on some very general and recognisable problems that everyone bumps into:
I wonder if it would be useful to have a (custom or buillt-in) KM action for tabulation of delimited rows ?
"Emplace".
Okay, I'll try again...
-Chris
--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2021/02/12 06:10
# dMod: 2021/02/12 06:37
# Appl: AppleScript
# Task: Create a Fixed-Width Table with Data 03.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Create, @Fixed_Width @Table
--------------------------------------------------------
set theData to paragraphs 2 thru -2 of "
7 - 9am Working
9 - 11am Meeting
11 - 11:30am Meeting
11:30am - 12:30pm Meeting
12:30pm - 1pm Working
2 - 5pm Working
"
property tableWidth : 29
property dotPad : "........................................"
set AppleScript's text item delimiters to {" "}
repeat with i in theData
tell i to set contents of i to (its text items 1 thru -2 as text) & space & (text 1 thru (tableWidth - 2 - ((length of (text items 1 thru -2 of i as text)) + (length of (last text item of i)))) of dotPad) & space & (its last text item)
end repeat
set AppleScript's text item delimiters to linefeed
return theData as text
--------------------------------------------------------
If I set the shell script action to display text in a window, everything looks great:
However, if I save the script result to a variable and then use the Display Text in a Window action, I get:
If I paste the misaligned output here, it looks fine:
Local__Test: [test1]
--------------------------------------------------------------------
Local__LongTestVariableName: [test2]
--------------------------------------------------------------------
So what gives?
Change the font of the display text action to a monospaced font.
I typically use Menlo 14.
Nice! Thanks Chris!
Here's an evolution of the same concept:
Align Text as Columns.kmmacros (23 KB)
Example input:
Instrument: Name: Wife: Years Married
Rhythm Guitar: John: Yoko: 69-80
Bass: Paul: Linda: 67-98
Lead Guitar: George: Pattie: 66-77
Drums: Ringo: Maureen: 65-75
Output:
Instrument Name Wife Years Married
Rhythm Guitar John Yoko 69-80
Bass Paul Linda 67-98
Lead Guitar George Pattie 66-77
Drums Ringo Maureen 65-75
Options:
Set to 0
, a single space will separate columns. Any positive value will add addional spaces.
Set the delimiter that will differentiate column bounds.
Thanks @noisneil for creating this macro. I don't need it right now, but I know I will need it one day.
ChrisQ
No worries. Here's another approach using tabs instead of spaces.
One thing I've noticed with the tab version is that if you paste it into TextEdit, for example, and then select a monospaced font, it's perfect.
However, if you write it to a file as styled text with the same font, the tabs occasionally come out a bit squiffy.
Any ideas why that might be?
A lot of shell utilities are going to expect monospaced fonts.
I'm using Menlo, which is monospaced.
No idea how this Keyboard Maestro Execute JavaScript for Automation action compares in terms of speed.
Monospaced columns (as defined by delimiter) separated by given gap.kmmacros (5.3 KB)
(() => {
"use strict";
// Columns of Text (as defined by given Delimiter),
// padded to even width, and separated by given Gap.
// Rob Trew @2023
// Ver 0.01
const main = () => {
const
kmVar = kmValue(kmInstance()),
[txt, delim, gap] = ["Text", "Delimiter", "Gap"]
.map(k => kmVar(`local_${k}`)),
rows = lines(txt).map(
row => row.split(delim).map(k => k.trim())
),
n = Math.max(...rows.map(row => row.length)),
fullRows = rows.map(row => {
const m = row.length;
return n === m
? row
: row.concat(
Array.from(
{length: n - m},
() => ""
)
);
});
return transpose(
transpose(fullRows).map(column => {
const
w = Math.max(
...column.map(cell => cell.length)
);
return column.map(
cell => cell.padEnd(w, " ")
);
})
)
.map(row => row.join(gap))
.join("\n");
};
// ---------------- KEYBOARD MAESTRO -----------------
// kmValue :: KM Instance -> String -> IO String
const kmValue = instance =>
k => Application("Keyboard Maestro Engine")
.getvariable(k, {instance});
// kmInstance :: () -> IO String
const kmInstance = () =>
ObjC.unwrap(
$.NSProcessInfo.processInfo.environment
.objectForKey("KMINSTANCE")
) || "";
// --------------------- GENERIC ---------------------
// lines :: String -> [String]
const lines = s =>
// A list of strings derived from a single string
// which is delimited by \n or by \r\n or \r.
0 < s.length
? s.split(/\r\n|\n|\r/u)
: [];
// transpose :: [[a]] -> [[a]]
const transpose = rows =>
// The columns of the input transposed
// into new rows.
// Simpler version of transpose, assuming input
// rows of even length.
0 < rows.length
? rows[0].map(
(_, i) => rows.flatMap(v => v[i])
)
: [];
// MAIN ---
return main();
})();
This version sets each column to an explicit character position. Useful if you want multiple text blocks to be formatted separately yet identically.
Align Text as Spaced Columns (Explicit Positions).kmmacros (22 KB)