diff --git a/src/components/Nvim/Nvim.tsx b/src/components/Nvim/Nvim.tsx index 115d95e..9891d16 100644 --- a/src/components/Nvim/Nvim.tsx +++ b/src/components/Nvim/Nvim.tsx @@ -1,12 +1,16 @@ +import { useApp } from "~/context/AppContext"; import { NvimStatusBar } from "./NvimStatusBar"; import { NvimTree } from "./NvimTree"; +import { buildFileTree } from "~/utils/filesystem"; export const Nvim = () => { + const manifest = useApp(); + return (
- +
diff --git a/src/components/Nvim/NvimTree.tsx b/src/components/Nvim/NvimTree.tsx index 6bd10af..7e1b91e 100644 --- a/src/components/Nvim/NvimTree.tsx +++ b/src/components/Nvim/NvimTree.tsx @@ -1,11 +1,14 @@ import { useState, useEffect } from "react"; -import { useApp } from "~/context/AppContext"; import { useTerminal } from "~/context/TerminalContext"; -import { FILE_STYLES, type File } from "~/utils/filesystem"; +import { + DEFAULT_FILE_STYLE, + FILE_STYLES, + getExtension, + type File, +} from "~/utils/filesystem"; import { type Cell } from "~/utils/terminal/cell"; import { TerminalRenderer } from "~/utils/terminal/renderer"; import { theme } from "~/utils/terminal/theme"; -import { type Manifest } from "~/utils/types"; const PATH_FOLDED: Cell = { char: "", @@ -17,39 +20,9 @@ const PATH_UNFOLDED: Cell = { foreground: theme.blue, }; -const buildFileTree = (manifest: Manifest): Array => { - if (manifest === undefined) return []; - - const files: Array = []; - manifest.projects.forEach(project => { - if (project.name === "pihkaal") { - project.files.forEach(file => { - files.push({ - name: file, - type: "md", - }); - }); - } else { - files.push({ - name: project.name, - type: "directory", - folded: true, - children: project.files.map(file => ({ - name: file, - type: "md", - })), - }); - } - }); - - return files; -}; - -export const NvimTree = () => { - const manifest = useApp(); - +export const NvimTree = (props: { files: Array }) => { const [selected, setSelected] = useState(0); - const [files, setFiles] = useState(buildFileTree(manifest)); + const [files, setFiles] = useState(props.files); const { cols: width, rows: height } = useTerminal(); const canvas = new TerminalRenderer(width * 0.2, height - 2, { @@ -63,12 +36,15 @@ export const NvimTree = () => { let indent = 0; const renderTree = (files: Array) => { files.forEach(file => { - tree.apply(2 + indent * 2, y, FILE_STYLES[file.type]); - if (file.type === "directory") { + tree.apply(2 + indent * 2, y, { + char: file.folded ? "\ue6ad" : "\ueaf6", + foreground: theme.blue, + }); + tree.apply(indent * 2, y, file.folded ? PATH_FOLDED : PATH_UNFOLDED); tree.write(4 + indent * 2, y, file.name, { - foreground: FILE_STYLES.directory.foreground, + foreground: theme.blue, }); y++; @@ -78,6 +54,10 @@ export const NvimTree = () => { indent--; } } else { + const style = + FILE_STYLES[getExtension(file.name)] ?? DEFAULT_FILE_STYLE; + tree.apply(2 + indent * 2, y, style); + if (file.name === "README.md") { tree.write(4 + indent * 2, y, file.name, { foreground: theme.yellow, @@ -146,13 +126,3 @@ export const NvimTree = () => { return

{canvas.render()}

; }; - -/* - .sort((a, b) => a.name.localeCompare(b.name)).sort((a, b) => - a.type === "directory" && b.type !== "directory" - ? -1 - : a.type !== "directory" && b.type === "directory" - ? 1 - : 0, - ), -*/ diff --git a/src/utils/filesystem.ts b/src/utils/filesystem.ts index 69844c2..818b724 100644 --- a/src/utils/filesystem.ts +++ b/src/utils/filesystem.ts @@ -1,11 +1,18 @@ import { type Cell } from "./terminal/cell"; import { theme } from "./terminal/theme"; +import { type Manifest } from "./types"; -export const FILE_STYLES = { - directory: { - char: "\ue6ad", // \ue6ad ||| \ueaf6 - foreground: theme.blue, - }, +export const getExtension = (path: string) => { + const parts = path.split("."); + return parts[Math.max(0, parts.length - 1)] ?? ""; +}; + +export const DEFAULT_FILE_STYLE: Cell = { + char: "F", + foreground: theme.white, +}; + +export const FILE_STYLES: Record = { md: { char: "\ue73e", foreground: theme.blue, @@ -14,15 +21,13 @@ export const FILE_STYLES = { char: "\uf43d", foreground: theme.yellow, }, -} as const satisfies Record; - -export type FileType = keyof typeof FILE_STYLES; +}; export type File = { name: string; } & ( | { - type: Exclude; + type: "file"; } | { type: "directory"; @@ -30,3 +35,42 @@ export type File = { folded: boolean; } ); + +const sortFiles = (files: Array) => + files + .sort((a, b) => a.name.localeCompare(b.name)) + .sort((a, b) => + a.type === "directory" && b.type !== "directory" + ? -1 + : a.type !== "directory" && b.type === "directory" + ? 1 + : 0, + ); + +export const buildFileTree = (manifest: Manifest): Array => { + const files: Array = []; + manifest.projects.forEach(project => { + if (project.name === "pihkaal") { + project.files.forEach(file => { + files.push({ + name: file, + type: "file", + }); + }); + } else { + files.push({ + name: project.name, + type: "directory", + folded: true, + children: sortFiles( + project.files.map(file => ({ + name: file, + type: "file", + })), + ), + }); + } + }); + + return sortFiles(files); +};