mirror of
https://github.com/EnumeratedDev/typer.git
synced 2026-09-21 07:36:11 +00:00
Compare commits
7
Commits
2f1978e6da
...
ef401b5aaa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef401b5aaa
|
||
|
|
612c0ba80c
|
||
|
|
d82d53d659
|
||
|
|
abafc12b47
|
||
|
|
811a8f7ee9
|
||
|
|
18462d1df9
|
||
|
|
b40d89dc43
|
@@ -0,0 +1,69 @@
|
||||
name: Publish nightly
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
paths:
|
||||
- "**"
|
||||
- "!*.md"
|
||||
- "!.github/**"
|
||||
- ".github/workflows/publish_nightly.yml"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
os: [linux, darwin, freebsd, windows]
|
||||
arch: [amd64, arm64]
|
||||
steps:
|
||||
- name: Setup environment
|
||||
run: echo "FILENAME=typer-nightly-$(date --iso-8601)-${{ matrix.os }}-${{ matrix.arch }}" >> $GITHUB_ENV
|
||||
- name: Fetch repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.24
|
||||
- name: Build using make
|
||||
run: make GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }}
|
||||
- name: Setup archive contents
|
||||
run: |
|
||||
mkdir -p staging/$FILENAME
|
||||
cp build/* -t staging/$FILENAME/
|
||||
cp -r config staging/$FILENAME/config
|
||||
- name: Create tarball
|
||||
if: matrix.os != 'windows'
|
||||
run: |
|
||||
cd staging
|
||||
tar -czvf $FILENAME.tar.gz $FILENAME
|
||||
- name: Create zip
|
||||
if: matrix.os == 'windows'
|
||||
run: |
|
||||
cd staging/$FILENAME
|
||||
zip -r ../$FILENAME.zip *
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-${{ matrix.os }}-${{ matrix.arch }}
|
||||
path: staging/${{ env.FILENAME }}.*
|
||||
publish:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
- name: Update nightly release
|
||||
uses: andelf/nightly-release@main
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: nightly
|
||||
name: Nightly
|
||||
body: |
|
||||
**This is the nightly release of Typer. Expect bugs and unfinished features**
|
||||
files: artifacts/*
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
/build/
|
||||
|
||||
# IDE files
|
||||
.idea
|
||||
/.idea
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
| Distribution | Package name |
|
||||
|:----------------------:|:---------------------|
|
||||
| Arch Linux/Artix Linux | `typer` from the AUR |
|
||||
| Tide Linux | `typer` from the main repository |
|
||||
#### From the releases section:
|
||||
- Go to the [releases section](https://github.com/EnumeratedDev/typer/releases)
|
||||
- Choose either the latest stable release (**Recommended**) or nightly pre-release
|
||||
- Download the archive that corresponds to your operating system and architecture
|
||||
- Optional: Add the extracted directory to your PATH so that typer can be launched from anywhere
|
||||
- Optional: On Unix-based systems you can move the `typer` executable into `/usr/local/bin/typer` and `config` directory into `/usr/local/etc/typer` for a system-wide installation
|
||||
#### From source:
|
||||
- Download `go` from your package manager or from the go website
|
||||
- Downlaod `which` from your package manager
|
||||
|
||||
+15
-42
@@ -3,8 +3,6 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -21,7 +19,7 @@ type TyperConfig struct {
|
||||
|
||||
var Config TyperConfig
|
||||
|
||||
func readConfig() {
|
||||
func readMainConfig() {
|
||||
Config = TyperConfig{
|
||||
SelectedStyle: "default",
|
||||
FallbackStyle: "default-fallback",
|
||||
@@ -32,49 +30,24 @@ func readConfig() {
|
||||
TabIndentation: 4,
|
||||
}
|
||||
|
||||
homeDir, err := os.UserHomeDir()
|
||||
// Get main config path
|
||||
mainConfigPath := GetConfigPath("config.yml")
|
||||
|
||||
// Ensure config exists at path
|
||||
if mainConfigPath == "" {
|
||||
log.Fatalf("config.yml not found in any config directory")
|
||||
}
|
||||
|
||||
// Read config file
|
||||
data, err := os.ReadFile(mainConfigPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get home directory: %s", err)
|
||||
log.Fatalf("Could not read config.yml: %s", err)
|
||||
}
|
||||
|
||||
execPath, err := os.Executable()
|
||||
// Unmarshal contents into struct
|
||||
err = yaml.Unmarshal(data, &Config)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get path to executable: %s", err)
|
||||
}
|
||||
|
||||
configPaths := make([]string, 0)
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, "AppData/Roaming/Typer/config.yml"))
|
||||
configPaths = append(configPaths, filepath.Join(filepath.Dir(execPath), "etc/typer/config.yml"))
|
||||
case "darwin":
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, "Library/Typer/config.yml"))
|
||||
configPaths = append(configPaths, "/Library/Typer/config.yml")
|
||||
configPaths = append(configPaths, filepath.Join(sysconfdir, "typer/config.yml"))
|
||||
default:
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, ".config/typer/config.yml"))
|
||||
configPaths = append(configPaths, filepath.Join(sysconfdir, "typer/config.yml"))
|
||||
}
|
||||
|
||||
for _, configPath := range configPaths {
|
||||
// Ensure config exists at path
|
||||
if _, err := os.Stat(configPath); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Read config file
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read config.yml: %s", err)
|
||||
}
|
||||
|
||||
// Unmarshal contents into struct
|
||||
err = yaml.Unmarshal(data, &Config)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not unmarshal config.yml: %s", err)
|
||||
}
|
||||
|
||||
break
|
||||
log.Fatalf("Could not unmarshal config.yml: %s", err)
|
||||
}
|
||||
|
||||
// Validate config options
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
|
||||
@@ -11,6 +11,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
|
||||
+15
-42
@@ -3,8 +3,6 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
@@ -23,54 +21,29 @@ type Keybinding struct {
|
||||
|
||||
var Keybindings TyperKeybindings
|
||||
|
||||
func readKeybindings() {
|
||||
func readKeybindingsConfig() {
|
||||
Keybindings = TyperKeybindings{
|
||||
Keybindings: make([]Keybinding, 0),
|
||||
}
|
||||
|
||||
homeDir, err := os.UserHomeDir()
|
||||
// Get keybindings config path
|
||||
keybindingsConfigPath := GetConfigPath("keybindings.yml")
|
||||
|
||||
// Ensure config exists at path
|
||||
if keybindingsConfigPath == "" {
|
||||
log.Fatalf("keybindings.yml not found in any config directory")
|
||||
}
|
||||
|
||||
// Read config file
|
||||
data, err := os.ReadFile(keybindingsConfigPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get home directory: %s", err)
|
||||
log.Fatalf("Could not read keybindings.yml: %s", err)
|
||||
}
|
||||
|
||||
execPath, err := os.Executable()
|
||||
// Unmarshal contents into struct
|
||||
err = yaml.Unmarshal(data, &Keybindings)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get path to executable: %s", err)
|
||||
}
|
||||
|
||||
configPaths := make([]string, 0)
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, "AppData/Roaming/Typer/keybindings.yml"))
|
||||
configPaths = append(configPaths, filepath.Join(filepath.Dir(execPath), "etc/typer/keybindings.yml"))
|
||||
case "darwin":
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, "Library/Typer/keybindings.yml"))
|
||||
configPaths = append(configPaths, "/Library/Typer/keybindings.yml")
|
||||
configPaths = append(configPaths, filepath.Join(sysconfdir, "typer/keybindings.yml"))
|
||||
default:
|
||||
configPaths = append(configPaths, filepath.Join(homeDir, ".config/typer/keybindings.yml"))
|
||||
configPaths = append(configPaths, filepath.Join(sysconfdir, "typer/keybindings.yml"))
|
||||
}
|
||||
|
||||
for _, configPath := range configPaths {
|
||||
// Ensure config exists at path
|
||||
if _, err := os.Stat(configPath); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Read config file
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read keybindings.yml: %s", err)
|
||||
}
|
||||
|
||||
// Unmarshal contents into struct
|
||||
err = yaml.Unmarshal(data, &Keybindings)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not unmarshal keybindings.yml: %s", err)
|
||||
}
|
||||
|
||||
break
|
||||
log.Fatalf("Could not unmarshal keybindings.yml: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-8
@@ -2,19 +2,25 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var sysconfdir = "/etc/"
|
||||
|
||||
var configDirFlag = flag.StringP("config", "c", "", "Path to config directory")
|
||||
|
||||
func main() {
|
||||
// Read config
|
||||
readConfig()
|
||||
// Read flags
|
||||
readFlags()
|
||||
|
||||
// Read key bindings
|
||||
readKeybindings()
|
||||
// Read main config
|
||||
readMainConfig()
|
||||
|
||||
// Read styles
|
||||
// Read keybindings config
|
||||
readKeybindingsConfig()
|
||||
|
||||
// Read styles directory
|
||||
readStyles()
|
||||
|
||||
// Initialize commands
|
||||
@@ -25,8 +31,8 @@ func main() {
|
||||
log.Fatalf("Failed to create window: %v", err)
|
||||
}
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
for i, file := range os.Args[1:] {
|
||||
if flag.NArg() > 0 {
|
||||
for i, file := range flag.Args() {
|
||||
b, err := CreateFileBuffer(file, true)
|
||||
if err != nil {
|
||||
window.PrintMessage("Could not open file: " + file)
|
||||
@@ -48,3 +54,7 @@ func main() {
|
||||
window.screen.Fini()
|
||||
window.screen = nil
|
||||
}
|
||||
|
||||
func readFlags() {
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
+18
-42
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -73,54 +72,31 @@ var AvailableStyles = make(map[string]TyperStyle)
|
||||
var CurrentStyle = FallbackStyle
|
||||
|
||||
func readStyles() {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
// Get styles directory path
|
||||
stylesDirPath := GetConfigPath("styles")
|
||||
|
||||
// Ensure directory exists at path
|
||||
if stat, err := os.Stat(stylesDirPath); stylesDirPath == "" || err != nil || !stat.IsDir() {
|
||||
return
|
||||
}
|
||||
|
||||
// Get directory entries
|
||||
entries, err := os.ReadDir(stylesDirPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get home directory: %s", err)
|
||||
log.Fatalf("Could not read user style directory: %s", err)
|
||||
}
|
||||
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get path to executable: %s", err)
|
||||
}
|
||||
// Read entries in directory
|
||||
for _, entry := range entries {
|
||||
entryPath := filepath.Join(stylesDirPath, entry.Name())
|
||||
|
||||
stylesPaths := make([]string, 0)
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
stylesPaths = append(stylesPaths, filepath.Join(homeDir, "AppData/Roaming/Typer/styles"))
|
||||
stylesPaths = append(stylesPaths, filepath.Join(filepath.Dir(execPath), "config/styles"))
|
||||
case "darwin":
|
||||
stylesPaths = append(stylesPaths, filepath.Join(homeDir, "Library/Typer/styles"))
|
||||
stylesPaths = append(stylesPaths, "/Library/Typer/styles")
|
||||
stylesPaths = append(stylesPaths, filepath.Join(sysconfdir, "typer/styles"))
|
||||
default:
|
||||
stylesPaths = append(stylesPaths, filepath.Join(homeDir, ".config/typer/styles"))
|
||||
stylesPaths = append(stylesPaths, filepath.Join(sysconfdir, "typer/styles"))
|
||||
}
|
||||
|
||||
for _, stylesPath := range stylesPaths {
|
||||
// Ensure directory exists at path
|
||||
if stat, err := os.Stat(stylesPath); err != nil || !stat.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get directory entries
|
||||
entries, err := os.ReadDir(stylesPath)
|
||||
style, err := readStyleYamlFile(entryPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read user style directory: %s", err)
|
||||
log.Fatalf("Could not read style file (%s): %s", entryPath, err)
|
||||
}
|
||||
|
||||
// Read entries in directory
|
||||
for _, entry := range entries {
|
||||
entryPath := filepath.Join(stylesPath, entry.Name())
|
||||
|
||||
style, err := readStyleYamlFile(entryPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read style file (%s): %s", entryPath, err)
|
||||
}
|
||||
|
||||
if _, ok := AvailableStyles[style.Name]; !ok {
|
||||
AvailableStyles[style.Name] = style
|
||||
}
|
||||
if _, ok := AvailableStyles[style.Name]; !ok {
|
||||
AvailableStyles[style.Name] = style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-1
@@ -1,6 +1,54 @@
|
||||
package main
|
||||
|
||||
import "github.com/gdamore/tcell/v2"
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
func GetConfigPath(relativeConfigPath string) string {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get home directory: %s", err)
|
||||
}
|
||||
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get path to executable: %s", err)
|
||||
}
|
||||
|
||||
paths := make([]string, 0)
|
||||
if *configDirFlag != "" {
|
||||
paths = append(paths, path.Join(*configDirFlag, relativeConfigPath))
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
paths = append(paths, filepath.Join(homeDir, "AppData/Roaming/Typer", relativeConfigPath))
|
||||
paths = append(paths, "C:/ProgramData/Typer", relativeConfigPath)
|
||||
case "darwin":
|
||||
paths = append(paths, filepath.Join(homeDir, "Library/Typer", relativeConfigPath))
|
||||
paths = append(paths, filepath.Join(homeDir, "Library/typer", relativeConfigPath))
|
||||
paths = append(paths, filepath.Join(sysconfdir, "Typer", relativeConfigPath))
|
||||
paths = append(paths, filepath.Join(sysconfdir, "typer", relativeConfigPath))
|
||||
default:
|
||||
paths = append(paths, filepath.Join(homeDir, ".config/typer", relativeConfigPath))
|
||||
paths = append(paths, filepath.Join(sysconfdir, "typer", relativeConfigPath))
|
||||
}
|
||||
paths = append(paths, filepath.Join(filepath.Dir(execPath), "config", relativeConfigPath))
|
||||
|
||||
for _, p := range paths {
|
||||
// Return true if path exists
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func drawText(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style, text string) {
|
||||
row := y1
|
||||
|
||||
Reference in New Issue
Block a user