feat: added bookmark directories

This commit is contained in:
Andre Henriques 2025-05-22 15:25:39 +01:00
parent 0135c64bab
commit a005fa994f
5 changed files with 351 additions and 154 deletions

70
app.go
View File

@ -3,8 +3,10 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"strings"
"github.com/wailsapp/wails/v2/pkg/runtime"
@ -15,12 +17,24 @@ type App struct {
ctx context.Context
inputList []string
remeberedPath []string
}
func GetRemeberPath() (string, error) {
homedir, err := os.UserHomeDir()
if err != nil {
return "", err
}
return fmt.Sprintf("%s/.config/railgun-remeber", homedir), nil
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{
inputList: []string{},
inputList: []string{},
remeberedPath: []string{},
}
}
@ -28,6 +42,24 @@ func NewApp() *App {
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
remeberPath, err := GetRemeberPath()
if err != nil {
return
}
if _, err := os.Stat(remeberPath); err != nil {
return
}
data, err := ioutil.ReadFile(remeberPath)
base := strings.Split(string(data), "\n")
a.remeberedPath = []string{}
for _, elm := range base {
if elm != "" {
a.remeberedPath = append(a.remeberedPath, elm)
}
}
}
func (a *App) Close() {
@ -81,6 +113,37 @@ func (a *App) SearchMathEql(value string) *string {
return nil
}
func (a *App) SearchRemeberDir(value string) []string {
if value == "" {
if len(a.remeberedPath) >= 5 {
return a.remeberedPath[0:6]
}
return a.remeberedPath
}
reg, err := regexp.Compile(value)
if err != nil {
return []string{}
}
if len(a.remeberedPath) == 0 {
return []string{}
}
n_list := []string{}
for _, elm := range a.remeberedPath {
if reg.MatchString(elm) {
n_list = append(n_list, elm)
}
if len(n_list) >= 5 {
return n_list
}
}
return n_list
}
// Greet returns a greeting for the given name
func (a *App) Search(value string) []string {
if len(a.inputList) == 0 {
@ -122,3 +185,8 @@ func (a *App) Enter(value string) {
fmt.Printf("%s", value)
runtime.Quit(a.ctx)
}
func (a *App) EnterDir(value string) {
fmt.Printf("ghostty --working-directory=%s", value)
runtime.Quit(a.ctx)
}

View File

@ -1,171 +1,206 @@
<script lang="ts">
import {
SearchMath,
Close,
SearchMathEql,
SearchDict,
Search,
Enter,
} from "../wailsjs/go/main/App.js";
import {
SearchMath,
Close,
SearchMathEql,
SearchDict,
Search,
Enter,
EnterDir,
SearchRemeberDir,
} from "../wailsjs/go/main/App.js";
let searchText: string;
let searchText: string;
let mathRes: string | null;
let eqRes: string | null;
let dictRes: string | null;
let search: string[] | null;
let selectedI: number = 0;
let mathRes: string | null;
let eqRes: string | null;
let dictRes: string | null;
let search: string[] | null;
let remeberSearch: string[] = [];
let selectedI: number = 0;
let searchBar: HTMLInputElement;
let searchBar: HTMLInputElement;
$: searchBar?.focus();
$: searchBar?.focus();
function findRes(searchText: string) {
Search(searchText).then((res: string[] | null) => {
search = res;
if (search && search.length < selectedI) {
selectedI = 0;
}
});
if (!searchText) {
mathRes = null;
eqRes = null;
dictRes = null;
return;
}
SearchMath(searchText).then((res: string | null) => {
mathRes = res;
});
SearchMathEql(searchText).then((res: string | null) => {
eqRes = res;
});
SearchDict(searchText).then((res: string | null) => {
dictRes = res;
});
}
function findRes(searchText: string) {
Search(searchText).then((res: string[] | null) => {
search = res;
if (search && search.length < selectedI) {
selectedI = 0;
}
});
SearchRemeberDir(searchText).then((res: string[] | null) => {
console.log("here", res);
remeberSearch = res ?? [];
});
if (!searchText) {
mathRes = null;
eqRes = null;
dictRes = null;
return;
}
SearchMath(searchText).then((res: string | null) => {
mathRes = res;
});
SearchMathEql(searchText).then((res: string | null) => {
eqRes = res;
});
SearchDict(searchText).then((res: string | null) => {
dictRes = res;
});
}
$: findRes(searchText);
$: findRes(searchText);
</script>
<main>
<div class="main">
<input
class="main-search"
bind:this={searchBar}
bind:value={searchText}
placeholder="Search"
on:keydown={(e) => {
if (e.key === "Escape") {
Close();
} else if (e.key === "ArrowDown") {
selectedI = Math.min(selectedI + 1, (search ?? []).length);
} else if (e.key === "ArrowUp") {
selectedI = Math.max(selectedI - 1, 0);
} else if (e.key === "Enter") {
if (search[selectedI]) {
Enter(search[selectedI]);
}
}
}}
/>
<div style="padding: 0 10px">
{#if searchText?.match(/^#[\da-f]{3}([\da-f]{3})?$/)}
<div style="display: flex; gap: 20px; align-items: center; padding: 20px;">
<h1>Color</h1>
<div class="color-block" style="--background-color: {searchText};"></div>
</div>
{/if}
{#if mathRes}
<div>
<h1>Calculations</h1>
<div class="math-res">
<b>&gt;</b>
{mathRes}
</div>
</div>
{/if}
{#if eqRes}
<div>
<h1>Equasion</h1>
<div class="math-res">
<b>&gt;</b>
{eqRes.substring(0, eqRes.length - 2)}
</div>
</div>
{/if}
{#if dictRes}
{@const data = JSON.parse(dictRes)[0]}
<div>
<h1>Dictionary ({data.word})</h1>
<div
style="color: white; max-height: {!search ||
search.length === 0
? '70vh'
: '20vh'}; overflow-y: auto;"
>
{@html data.definition}
</div>
</div>
{/if}
{#if search}
<div style="overflow: auto; max-height: 600px;">
{#each search as item, i}
<div
style="color: white; font-size: 18px; padding: 10px 5px; background: {selectedI ===
i
? 'oklch(71.4% 0.203 305.504 / 20)'
: ''}"
>
{item}
</div>
{/each}
</div>
{/if}
</div>
</div>
<div class="main">
<input
class="main-search"
bind:this={searchBar}
bind:value={searchText}
placeholder="Search"
on:keydown={(e) => {
if (e.key === "Escape") {
Close();
} else if (e.key === "ArrowDown") {
selectedI = Math.min(
selectedI + 1,
(search ?? []).length + (remeberSearch ?? []).length,
);
} else if (e.key === "ArrowUp") {
selectedI = Math.max(selectedI - 1, 0);
} else if (e.key === "Enter") {
if (selectedI < remeberSearch.length) {
EnterDir(remeberSearch[selectedI]);
return;
}
if (search[selectedI - remeberSearch.length]) {
Enter(search[selectedI - remeberSearch.length]);
}
}
}}
/>
<div style="padding: 0 10px">
{#if remeberSearch.length > 0}
<div
style="overflow: auto; max-height: 600px; border-bottom: 1px #fff solid; margin-bottom: 10px;"
>
<h1>Remebered Paths</h1>
{#each remeberSearch as item, i}
<div
style="color: white; font-size: 18px; padding: 10px 5px; background: {selectedI ===
i
? 'oklch(71.4% 0.203 305.504 / 20)'
: ''}"
>
{item}
</div>
{/each}
</div>
{/if}
{#if searchText?.match(/^#[\da-f]{3}([\da-f]{3})?$/)}
<div
style="display: flex; gap: 20px; align-items: center; padding: 20px;"
>
<h1>Color</h1>
<div
class="color-block"
style="--background-color: {searchText};"
></div>
</div>
{/if}
{#if mathRes}
<div>
<h1>Calculations</h1>
<div class="math-res">
<b>&gt;</b>
{mathRes}
</div>
</div>
{/if}
{#if eqRes}
<div>
<h1>Equasion</h1>
<div class="math-res">
<b>&gt;</b>
{eqRes.substring(0, eqRes.length - 2)}
</div>
</div>
{/if}
{#if dictRes}
{@const data = JSON.parse(dictRes)[0]}
<div style="margin-bottom: 10px; border-bottom: 1px #fff solid;">
<h1>Dictionary ({data.word})</h1>
<div
style="color: white; max-height: {!search || search.length === 0
? '70vh'
: '20vh'}; overflow-y: auto;"
>
{@html data.definition}
</div>
</div>
{/if}
{#if search}
<div style="overflow: auto; max-height: 600px;">
{#each search as item, i}
<div
style="color: white; font-size: 18px; padding: 10px 5px; background: {selectedI ===
i + (remeberSearch ?? []).length
? 'oklch(71.4% 0.203 305.504 / 20)'
: ''}"
>
{item}
</div>
{/each}
</div>
{/if}
</div>
</div>
</main>
<style>
:global(html) {
overflow: hidden;
}
main {
height: 600px;
padding: 20px;
overflow: hidden;
}
:global(html) {
overflow: hidden;
}
main {
height: 600px;
padding: 20px;
overflow: hidden;
}
.main {
background: #181818;
border-radius: 10px;
height: 100%;
}
.main {
background: #181818;
border-radius: 10px;
height: 100%;
}
h1 {
color: white;
padding: 10px 0 5px 0;
margin: 0;
}
h1 {
color: white;
padding: 10px 0 5px 0;
margin: 0;
}
.math-res {
color: white;
font-size: 20px;
}
.math-res {
color: white;
font-size: 20px;
}
.main-search {
background: #181818;
height: 20px;
width: 98%;
padding: 5px;
font-size: 20px;
outline: none;
color: white;
border-radius: 10px;
border: #151515 solid 2px;
}
.color-block {
background: var(--background-color);
width: 64px;
height: 64px;
}
.main-search {
background: #181818;
height: 20px;
width: 98%;
padding: 5px;
font-size: 20px;
outline: none;
color: white;
border-radius: 10px;
border: #151515 solid 2px;
}
.color-block {
background: var(--background-color);
width: 64px;
height: 64px;
}
</style>

View File

@ -5,6 +5,8 @@ export function Close():Promise<void>;
export function Enter(arg1:string):Promise<void>;
export function EnterDir(arg1:string):Promise<void>;
export function Search(arg1:string):Promise<Array<string>>;
export function SearchDict(arg1:string):Promise<any>;
@ -12,3 +14,5 @@ export function SearchDict(arg1:string):Promise<any>;
export function SearchMath(arg1:string):Promise<any>;
export function SearchMathEql(arg1:string):Promise<any>;
export function SearchRemeberDir(arg1:string):Promise<Array<string>>;

View File

@ -10,6 +10,10 @@ export function Enter(arg1) {
return window['go']['main']['App']['Enter'](arg1);
}
export function EnterDir(arg1) {
return window['go']['main']['App']['EnterDir'](arg1);
}
export function Search(arg1) {
return window['go']['main']['App']['Search'](arg1);
}
@ -25,3 +29,7 @@ export function SearchMath(arg1) {
export function SearchMathEql(arg1) {
return window['go']['main']['App']['SearchMathEql'](arg1);
}
export function SearchRemeberDir(arg1) {
return window['go']['main']['App']['SearchRemeberDir'](arg1);
}

82
main.go
View File

@ -2,6 +2,11 @@ package main
import (
"embed"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
@ -13,6 +18,83 @@ import (
var assets embed.FS
func main() {
if len(os.Args) > 1 {
if os.Args[1] == "--remeber" {
path, err := os.Getwd()
if err != nil {
log.Fatal("Could not get working directory", err)
return
}
remeber_path, err := GetRemeberPath()
if err != nil {
log.Fatal("Could not create/open the remeber file")
return
}
data, err := ioutil.ReadFile(remeber_path)
if err != nil {
log.Fatal("Could not read the remeber file")
return
}
if strings.Contains(fmt.Sprintf("%s\n", path), string(data)) {
log.Fatal("This path is already remebered")
return
}
f, err := os.OpenFile(remeber_path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
log.Fatal("Could not create/open the remeber file")
return
}
defer f.Close()
if _, err = f.WriteString(fmt.Sprintf("%s\n", path)); err != nil {
log.Fatal("Could not remeber", err)
}
fmt.Printf("Remebered: %s\n", path)
} else if os.Args[1] == "--forget" {
path, err := os.Getwd()
if err != nil {
log.Fatal("Could not get working directory", err)
return
}
remeber_path, err := GetRemeberPath()
if err != nil {
log.Fatal("Could not create/open the remeber file")
return
}
data, err := ioutil.ReadFile(remeber_path)
if err != nil {
log.Fatal("Could not read the remeber file")
return
}
if !strings.Contains(fmt.Sprintf("%s\n", path), string(data)) {
fmt.Printf("Forgotten*: %s\n", path)
return
}
base := strings.Split(string(data), "\n")
n_list := []string{}
for _, elm := range base {
if elm != path {
n_list = append(n_list, elm)
}
}
os.WriteFile(remeber_path, []byte(strings.Join(n_list, "\n")), 0666)
fmt.Printf("Forgotten: %s\n", path)
} else {
log.Fatal("Unkown option")
return
}
return
}
// Create an instance of the app structure
app := NewApp()