mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-09 20:44:03 -08:00
fix(image): use fixed image width
This commit is contained in:
parent
59be189233
commit
fece104e73
|
@ -12,11 +12,11 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
author string
|
||||
cursorPadding int
|
||||
rPromptOffset int
|
||||
bgColor string
|
||||
outputImage string
|
||||
author string
|
||||
// cursorPadding int
|
||||
// rPromptOffset int
|
||||
bgColor string
|
||||
outputImage string
|
||||
)
|
||||
|
||||
// imageCmd represents the image command
|
||||
|
@ -49,10 +49,12 @@ Exports the config to an image file using customized output options.`,
|
|||
Run: func(_ *cobra.Command, _ []string) {
|
||||
env := &platform.Shell{
|
||||
CmdFlags: &platform.Flags{
|
||||
Config: config,
|
||||
Shell: shell.GENERIC,
|
||||
Config: config,
|
||||
Shell: shell.GENERIC,
|
||||
TerminalWidth: 150,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
cfg := engine.LoadConfig(env)
|
||||
|
@ -80,12 +82,10 @@ Exports the config to an image file using customized output options.`,
|
|||
prompt := eng.Primary()
|
||||
|
||||
imageCreator := &engine.ImageRenderer{
|
||||
AnsiString: prompt,
|
||||
Author: author,
|
||||
CursorPadding: cursorPadding,
|
||||
RPromptOffset: rPromptOffset,
|
||||
BgColor: bgColor,
|
||||
Ansi: writer,
|
||||
AnsiString: prompt,
|
||||
Author: author,
|
||||
BgColor: bgColor,
|
||||
Ansi: writer,
|
||||
}
|
||||
|
||||
if outputImage != "" {
|
||||
|
@ -108,8 +108,8 @@ Exports the config to an image file using customized output options.`,
|
|||
func init() { //nolint:gochecknoinits
|
||||
imageCmd.Flags().StringVar(&author, "author", "", "config author")
|
||||
imageCmd.Flags().StringVar(&bgColor, "background-color", "", "image background color")
|
||||
imageCmd.Flags().IntVar(&cursorPadding, "cursor-padding", 0, "prompt cursor padding")
|
||||
imageCmd.Flags().IntVar(&rPromptOffset, "rprompt-offset", 0, "right prompt offset")
|
||||
// imageCmd.Flags().IntVar(&cursorPadding, "cursor-padding", 0, "prompt cursor padding")
|
||||
// imageCmd.Flags().IntVar(&rPromptOffset, "rprompt-offset", 0, "right prompt offset")
|
||||
imageCmd.Flags().StringVarP(&outputImage, "output", "o", "", "image file (.png) to export to")
|
||||
exportCmd.AddCommand(imageCmd)
|
||||
}
|
||||
|
|
|
@ -339,6 +339,73 @@ func (ir *ImageRenderer) runeAdditionalWidth(r rune) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) cleanContent() {
|
||||
// clean abundance of empty lines
|
||||
ir.AnsiString = strings.Trim(ir.AnsiString, "\n")
|
||||
ir.AnsiString = "\n" + ir.AnsiString
|
||||
|
||||
// clean string before render
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[m", "\x1b[0m")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[K", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[0J", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[27m", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b8", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\u2800", " ")
|
||||
|
||||
// cursor indication
|
||||
saveCursorAnsi := "\x1b7"
|
||||
if !strings.Contains(ir.AnsiString, saveCursorAnsi) {
|
||||
ir.AnsiString += "_"
|
||||
}
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, saveCursorAnsi, "_")
|
||||
|
||||
// replace rprompt with adding and mark right aligned blocks with a pointer
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[1000C", strings.Repeat(" ", ir.RPromptOffset))
|
||||
|
||||
// add watermarks
|
||||
ir.AnsiString += "\n\n\x1b[1mohmyposh.dev\x1b[22m"
|
||||
if len(ir.Author) > 0 {
|
||||
createdBy := fmt.Sprintf(" by \x1b[1m%s\x1b[22m", ir.Author)
|
||||
ir.AnsiString += createdBy
|
||||
}
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) measureContent() (width, height float64) {
|
||||
linewidth := 145
|
||||
linewidth += ir.additionalWidth()
|
||||
|
||||
tmpDrawer := &font.Drawer{Face: ir.regular}
|
||||
advance := tmpDrawer.MeasureString(strings.Repeat(" ", linewidth))
|
||||
width = float64(advance >> 6)
|
||||
// height, lines times font height and line spacing
|
||||
height = float64(len(strings.Split(ir.AnsiString, "\n"))) * ir.fontHeight() * ir.lineSpacing
|
||||
return width, height
|
||||
}
|
||||
|
||||
/*
|
||||
additionalWidth returns the number of additional characters of width to allocate when drawing
|
||||
for characters that are 2 wide. A standard character will return 0
|
||||
Nerd Font glyphs will return 1, since most are double width
|
||||
*/
|
||||
func (ir *ImageRenderer) additionalWidth() int {
|
||||
longest := 0
|
||||
var longestLine string
|
||||
for _, line := range strings.Split(ir.AnsiString, "\n") {
|
||||
length := ir.lenWithoutANSI(line)
|
||||
if length > longest {
|
||||
longestLine = line
|
||||
longest = length
|
||||
}
|
||||
}
|
||||
|
||||
var additionalWidth int
|
||||
for _, rune := range longestLine {
|
||||
additionalWidth += ir.runeAdditionalWidth(rune)
|
||||
}
|
||||
|
||||
return additionalWidth
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) lenWithoutANSI(text string) int {
|
||||
if len(text) == 0 {
|
||||
return 0
|
||||
|
@ -363,57 +430,6 @@ func (ir *ImageRenderer) lenWithoutANSI(text string) int {
|
|||
return length
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) calculateWidth() int {
|
||||
longest := 0
|
||||
for _, line := range strings.Split(ir.AnsiString, "\n") {
|
||||
length := ir.lenWithoutANSI(line)
|
||||
if length > longest {
|
||||
longest = length
|
||||
}
|
||||
}
|
||||
return longest
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) cleanContent() {
|
||||
rPromptAnsi := "\x1b7\x1b[1000C"
|
||||
hasRPrompt := strings.Contains(ir.AnsiString, rPromptAnsi)
|
||||
// clean abundance of empty lines
|
||||
ir.AnsiString = strings.Trim(ir.AnsiString, "\n")
|
||||
ir.AnsiString = "\n" + ir.AnsiString
|
||||
// clean string before render
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[m", "\x1b[0m")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[K", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[0J", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[27m", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[1F", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b8", "")
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\u2800", " ")
|
||||
// replace rprompt with adding and mark right aligned blocks with a pointer
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, rPromptAnsi, fmt.Sprintf("_%s", strings.Repeat(" ", ir.CursorPadding)))
|
||||
ir.AnsiString = strings.ReplaceAll(ir.AnsiString, "\x1b[1000C", strings.Repeat(" ", ir.RPromptOffset))
|
||||
if !hasRPrompt {
|
||||
ir.AnsiString += fmt.Sprintf("_%s", strings.Repeat(" ", ir.CursorPadding))
|
||||
}
|
||||
// add watermarks
|
||||
ir.AnsiString += "\n\n\x1b[1mohmyposh.dev\x1b[22m"
|
||||
if len(ir.Author) > 0 {
|
||||
createdBy := fmt.Sprintf(" by \x1b[1m%s\x1b[22m", ir.Author)
|
||||
ir.AnsiString += createdBy
|
||||
}
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) measureContent() (width, height float64) {
|
||||
// get the longest line
|
||||
linewidth := ir.calculateWidth()
|
||||
// width, taken from the longest line
|
||||
tmpDrawer := &font.Drawer{Face: ir.regular}
|
||||
advance := tmpDrawer.MeasureString(strings.Repeat(" ", linewidth))
|
||||
width = float64(advance >> 6)
|
||||
// height, lines times font height and line spacing
|
||||
height = float64(len(strings.Split(ir.AnsiString, "\n"))) * ir.fontHeight() * ir.lineSpacing
|
||||
return width, height
|
||||
}
|
||||
|
||||
func (ir *ImageRenderer) SavePNG() error {
|
||||
var f = func(value float64) float64 { return ir.factor * value }
|
||||
|
||||
|
|
|
@ -8,10 +8,8 @@ const exec = util.promisify(require('child_process').exec);
|
|||
const themesConfigDir = "./../themes";
|
||||
const themesStaticDir = "./static/img/themes";
|
||||
|
||||
function newThemeConfig(rpromptOffset = 40, cursorPadding = 30, author = "", bgColor = "#151515") {
|
||||
function newThemeConfig(author = "", bgColor = "#151515") {
|
||||
var config = {
|
||||
rpromptOffset: rpromptOffset,
|
||||
cursorPadding: cursorPadding,
|
||||
author: author,
|
||||
bgColor: bgColor
|
||||
};
|
||||
|
@ -23,51 +21,18 @@ function isValidTheme(theme) {
|
|||
}
|
||||
|
||||
let themeConfigOverrrides = new Map();
|
||||
themeConfigOverrrides.set('agnoster.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('agnosterplus.omp.json', newThemeConfig(80));
|
||||
themeConfigOverrrides.set('amro.omp.json', newThemeConfig(40, 100, 'AmRo', '#1C2029'));
|
||||
themeConfigOverrrides.set('avit.omp.json', newThemeConfig(40, 80));
|
||||
themeConfigOverrrides.set('blueish.omp.json', newThemeConfig(40, 100));
|
||||
themeConfigOverrrides.set('cert.omp.json', newThemeConfig(40, 50));
|
||||
themeConfigOverrrides.set('chips.omp.json', newThemeConfig(25, 30, 'CodexLink | v1.2.4, Single Width (07/11/2023) | https://github.com/CodexLink/chips.omp.json'));
|
||||
themeConfigOverrrides.set('cinnamon.omp.json', newThemeConfig(40, 80));
|
||||
themeConfigOverrrides.set('craver.omp.json', newThemeConfig(40, 80, 'Nick Craver', '#282c34'));
|
||||
themeConfigOverrrides.set('darkblood.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('honukai.omp.json', newThemeConfig(20));
|
||||
themeConfigOverrrides.set('hotstick.minimal.omp.json', newThemeConfig(40, 10));
|
||||
themeConfigOverrrides.set('hunk.omp.json', newThemeConfig(40, 15, 'Paris Qian'));
|
||||
themeConfigOverrrides.set('huvix.omp.json', newThemeConfig(40, 70));
|
||||
themeConfigOverrrides.set('jandedobbeleer.omp.json', newThemeConfig(40, 15));
|
||||
themeConfigOverrrides.set('kushal.omp.json', newThemeConfig(90, 30, 'Kushal-Chandar'));
|
||||
themeConfigOverrrides.set('lambda.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('marcduiker.omp.json', newThemeConfig(0, 40));
|
||||
themeConfigOverrrides.set('material.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('microverse-power.omp.json', newThemeConfig(40, 100));
|
||||
themeConfigOverrrides.set('negligible.omp.json', newThemeConfig(10));
|
||||
themeConfigOverrrides.set('night-owl.omp.json', newThemeConfig(40, 0, 'Mr-Vipi', '#011627'));
|
||||
themeConfigOverrrides.set('paradox.omp.json', newThemeConfig(40, 100));
|
||||
themeConfigOverrrides.set('powerlevel10k_classic.omp.json', newThemeConfig(10));
|
||||
themeConfigOverrrides.set('powerlevel10k_lean.omp.json', newThemeConfig(80));
|
||||
themeConfigOverrrides.set('powerline.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('pure.omp.json', newThemeConfig(40, 80));
|
||||
themeConfigOverrrides.set('quick-term.omp.json', newThemeConfig(15, 0, 'SokLay'))
|
||||
themeConfigOverrrides.set('remk.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('robbyrussell.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('slim.omp.json', newThemeConfig(10, 80));
|
||||
themeConfigOverrrides.set('slimfat.omp.json', newThemeConfig(10, 93));
|
||||
themeConfigOverrrides.set('space.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('spaceship.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('star.omp.json', newThemeConfig(40, 70));
|
||||
themeConfigOverrrides.set('stelbent.minimal.omp.json', newThemeConfig(70));
|
||||
themeConfigOverrrides.set('tonybaloney.omp.json', newThemeConfig(0, 40));
|
||||
themeConfigOverrrides.set('unicorn.omp.json', newThemeConfig(0, 40));
|
||||
themeConfigOverrrides.set('ys.omp.json', newThemeConfig(40, 100));
|
||||
themeConfigOverrrides.set('zash.omp.json', newThemeConfig(40, 40));
|
||||
themeConfigOverrrides.set('catppuccin.omp.json', newThemeConfig(40, 40, 'IrwinJuice', '#24273A'));
|
||||
themeConfigOverrrides.set('catppuccin_latte.omp.json', newThemeConfig(40, 40, 'IrwinJuice', '#EFF1F5'));
|
||||
themeConfigOverrrides.set('catppuccin_frappe.omp.json', newThemeConfig(40, 40, 'IrwinJuice', '#303446'));
|
||||
themeConfigOverrrides.set('catppuccin_macchiato.omp.json', newThemeConfig(40, 40, 'IrwinJuice', '#24273A'));
|
||||
themeConfigOverrrides.set('catppuccin_mocha.omp.json', newThemeConfig(40, 40, 'IrwinJuice', '#1E1E2E'));
|
||||
themeConfigOverrrides.set('amro.omp.json', newThemeConfig('AmRo', '#1C2029'));
|
||||
themeConfigOverrrides.set('chips.omp.json', newThemeConfig('CodexLink | v1.2.4, Single Width (07/11/2023) | https://github.com/CodexLink/chips.omp.json'));
|
||||
themeConfigOverrrides.set('craver.omp.json', newThemeConfig('Nick Craver', '#282c34'));
|
||||
themeConfigOverrrides.set('hunk.omp.json', newThemeConfig('Paris Qian'));
|
||||
themeConfigOverrrides.set('kushal.omp.json', newThemeConfig('Kushal-Chandar'));
|
||||
themeConfigOverrrides.set('night-owl.omp.json', newThemeConfig('Mr-Vipi', '#011627'));
|
||||
themeConfigOverrrides.set('quick-term.omp.json', newThemeConfig('SokLay'))
|
||||
themeConfigOverrrides.set('catppuccin.omp.json', newThemeConfig('IrwinJuice', '#24273A'));
|
||||
themeConfigOverrrides.set('catppuccin_latte.omp.json', newThemeConfig('IrwinJuice', '#EFF1F5'));
|
||||
themeConfigOverrrides.set('catppuccin_frappe.omp.json', newThemeConfig('IrwinJuice', '#303446'));
|
||||
themeConfigOverrrides.set('catppuccin_macchiato.omp.json', newThemeConfig('IrwinJuice', '#24273A'));
|
||||
themeConfigOverrrides.set('catppuccin_mocha.omp.json', newThemeConfig('IrwinJuice', '#1E1E2E'));
|
||||
|
||||
(async () => {
|
||||
const themes = await fs.promises.readdir(themesConfigDir);
|
||||
|
@ -85,10 +50,7 @@ themeConfigOverrrides.set('catppuccin_mocha.omp.json', newThemeConfig(40, 40, 'I
|
|||
}
|
||||
|
||||
let poshCommand = `oh-my-posh config export image --config=${configPath}`;
|
||||
poshCommand += ` --rprompt-offset=${config.rpromptOffset}`;
|
||||
poshCommand += ` --cursor-padding=${config.cursorPadding}`;
|
||||
poshCommand += ` --background-color=${config.bgColor}`;
|
||||
poshCommand += ` --terminal-width=200`;
|
||||
if (config.author !== '') {
|
||||
poshCommand += ` --author="${config.author}"`;
|
||||
}
|
||||
|
@ -100,6 +62,8 @@ themeConfigOverrrides.set('catppuccin_mocha.omp.json', newThemeConfig(40, 40, 'I
|
|||
continue;
|
||||
}
|
||||
|
||||
console.info(`Exported ${theme}`);
|
||||
|
||||
const themeName = theme.slice(0, -9);
|
||||
const image = themeName + '.png';
|
||||
const toPath = path.join(themesStaticDir, image);
|
||||
|
|
Loading…
Reference in a new issue