Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support bulk renaming files in nightly yazi (opt-in) #152

Merged
merged 4 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,44 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Set up yazi
- name: Set up ripgrep
# it's a telescope dependency
run: |
# Install yazi
test -d _yazi || {
mkdir -p _yazi
wget "https://github.com/sxyazi/yazi/releases/download/v0.2.5/yazi-x86_64-unknown-linux-gnu.zip" --output-document yazi.zip
unzip yazi.zip -d _yazi
which rg || {
sudo apt-get install ripgrep
}
echo "Current _yazi/ contents"
ls -R _yazi

# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
echo "${PWD}/_yazi/yazi-x86_64-unknown-linux-gnu/" >> $GITHUB_PATH
- name: Compile and install `yazi-fm` from source
uses: baptiste0928/cargo-install@v3
with:
# yazi-fm is the `yazi` executable
crate: yazi-fm
git: https://github.com/sxyazi/yazi
# feat: ownership linemode (#1238)
# https://github.com/sxyazi/yazi/commit/11547eefe0346006a1a82455577784a34d67c9b7
commit: 11547eefe0346006a1a82455577784a34d67c9b7

- name: Compile and install yazi from source
uses: baptiste0928/cargo-install@v3
with:
# yazi-cli is the `ya` command line interface
crate: yazi-cli
git: https://github.com/sxyazi/yazi
# feat: ownership linemode (#1238)
# https://github.com/sxyazi/yazi/commit/11547eefe0346006a1a82455577784a34d67c9b7
commit: 11547eefe0346006a1a82455577784a34d67c9b7

- name: Run tests
uses: nvim-neorocks/nvim-busted-action@v1
with:
nvim_version: ${{ matrix.neovim_version }}
luarocks_version: "3.11.1"
- name: Set up ripgrep
run: |
which rg || {
sudo apt-get install ripgrep
}

# Install npm dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/[email protected]
with:
command: npm run cy:run

- uses: actions/upload-artifact@v4
# add the line below to store screenshots only on failures
# if: failure()
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ integration-tests/server/build/server.js
integration-tests/pid.txt
integration-tests/server/build
*.pem
integration-tests/test-environment/testdirs
3 changes: 3 additions & 0 deletions .luarc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"diagnostics.globals": ["finally"]
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ init:

lint:
selene ./lua/ ./spec/
@if grep -r -e "#focus" --include \*.lua .; then \
@if grep -r -e "#focus" --include \*.lua ./spec/; then \
echo "\n"; \
echo "Error: ${COLOR_GREEN}#focus${COLOR_RESET} tags found in the codebase.\n"; \
echo "Please remove them to prevent issues with not accidentally running all tests."; \
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ You can optionally configure yazi.nvim by setting any of the options below.
-- }
open_for_directories = false,

-- an upcoming optional feature. See
-- https://github.com/mikavilpas/yazi.nvim/pull/152
use_ya_for_events_reading = false,

-- the floating window scaling factor. 1 means 100%, 0.9 means 90%, etc.
floating_window_scaling_factor = 0.9,

Expand Down
22 changes: 17 additions & 5 deletions integration-tests/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { FitAddon } from "@xterm/addon-fit"
import { Terminal } from "@xterm/xterm"
import io from "socket.io-client"
import type {
StartAppMessage,
StartNeovimMessage,
StdinMessage,
StdoutMessage,
} from "../server/server"
import "./startAppGlobalType"
import type { StartAppMessageArguments } from "./startAppGlobalType"
import type {
StartNeovimArguments,
StartNeovimServerArguments,
} from "./testEnvironmentTypes"

const app = document.querySelector<HTMLDivElement>("#app")
if (!app) {
Expand Down Expand Up @@ -73,8 +75,18 @@ socket.on("disconnect", (reason) => {
console.log("disconnected: ", reason)
})

window.startApp = function startApp(args: StartAppMessageArguments) {
socket.emit("startApp" satisfies StartAppMessage, args)
window.startNeovim = async function startApp(
directory: string,
startArgs?: StartNeovimArguments,
) {
await socket.emitWithAck(
"startNeovim" satisfies StartNeovimMessage,
{
directory,
filename: startArgs?.filename ?? "initial-file.txt",
startupScriptModifications: startArgs?.startupScriptModifications,
} satisfies StartNeovimServerArguments,
)
}

socket.on(
Expand Down
12 changes: 0 additions & 12 deletions integration-tests/client/startAppGlobalType.ts

This file was deleted.

65 changes: 65 additions & 0 deletions integration-tests/client/testEnvironmentTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/** The arguments given from the tests to send to the server */
export type StartNeovimArguments = {
filename?: TestDirectoryFile | "."
startupScriptModifications?: StartupScriptModification[]
}

/** The arguments given to the server */
export type StartNeovimServerArguments = {
directory: string
} & StartNeovimArguments

export type StartupScriptModification =
"modify_yazi_config_to_use_ya_as_event_reader.lua"

declare global {
interface Window {
startNeovim(
directory: string,
startArguments?: StartNeovimArguments,
): Promise<void>
}
}

export type FileEntry = {
/** The name of the file and its extension.
* @example "file.txt"
*/
name: string

/** The name of the file without its extension.
* @example "file"
*/
stem: string

/** The extension of the file.
* @example ".txt"
*/
extension: string
}

/** Describes the contents of the test directory, which is a blueprint for
* files and directories. Tests can create a unique, safe environment for
* interacting with the contents of such a directory.
*
* Having strong typing for the test directory contents ensures that tests can
* be written with confidence that the files and directories they expect are
* actually found. Otherwise the tests are brittle and can break easily.
*/
export type TestDirectory = {
/** The path to the unique test directory itself (the root). */
rootPath: string

contents: {
["initial-file.txt"]: FileEntry
["test.lua"]: FileEntry
["file.txt"]: FileEntry
["subdirectory/sub.txt"]: FileEntry
["routes/posts.$postId/route.tsx"]: FileEntry
["routes/posts.$postId/adjacent-file.tsx"]: FileEntry
}
}

type TestDirectoryFile = keyof TestDirectory["contents"]

export {}
134 changes: 132 additions & 2 deletions integration-tests/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,139 @@
import assert from "assert"
import { execSync, Serializable } from "child_process"
import { defineConfig } from "cypress"
import { constants } from "fs"
import { access, mkdir, mkdtemp, readdir, readFile, rm } from "fs/promises"
import path from "path"
import { fileURLToPath } from "url"
import type { TestDirectory } from "./cypress/support/commands"

const __dirname = fileURLToPath(new URL(".", import.meta.resolve(".")))

// const file = "./test-environment/.repro/state/nvim/yazi.log"
const yaziLogFile = path.join(
__dirname,
"test-environment",
".repro",
"state",
"nvim",
"yazi.log",
)

console.log(`yaziLogFile: ${yaziLogFile}`)

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
setupNodeEvents(on, _config) {
on("after:browser:launch", async (): Promise<void> => {
// delete everything under the ./test-environment/testdirs/ directory
const testdirs = path.join(__dirname, "test-environment", "testdirs")
await mkdir(testdirs, { recursive: true })
const files = await readdir(testdirs)

console.log("Cleaning up testdirs directory...")

for (const file of files) {
const testdir = path.join(testdirs, file)
console.log(`Removing ${testdir}`)
await rm(testdir, { recursive: true })
}
})

on("task", {
async removeYaziLog() {
try {
await rm(yaziLogFile)
} catch (err) {
if (err.code !== "ENOENT") {
console.error(err)
}
}
return null // something must be returned
},
async showYaziLog() {
try {
const log = await readFile(yaziLogFile, "utf-8")
console.log(`${yaziLogFile}`, log.split("\n"))
return null
} catch (err) {
console.error(err)
return null // something must be returned
}
},
async createTempDir(): Promise<TestDirectory> {
try {
const dir = await createUniqueDirectory()

const directory: TestDirectory = {
rootPath: dir,
contents: {
"initial-file.txt": {
name: "initial-file.txt",
stem: "initial-file",
extension: ".txt",
},
"test.lua": {
name: "test.lua",
stem: "test",
extension: ".lua",
},
"file.txt": {
name: "file.txt",
stem: "file",
extension: ".txt",
},
"subdirectory/sub.txt": {
name: "sub.txt",
stem: "sub",
extension: ".txt",
},
"routes/posts.$postId/adjacent-file.tsx": {
name: "adjacent-file.tsx",
stem: "adjacent-file",
extension: ".tsx",
},
"routes/posts.$postId/route.tsx": {
name: "route.tsx",
stem: "route",
extension: ".tsx",
},
},
}
directory satisfies Serializable // required by cypress

execSync(`cp ./test-environment/initial-file.txt ${dir}/`)
execSync(`cp ./test-environment/file.txt ${dir}/`)
execSync(`cp ./test-environment/test-setup.lua ${dir}/test.lua`)
execSync(`cp -r ./test-environment/subdirectory ${dir}/`)
execSync(`cp -r ./test-environment/config-modifications/ ${dir}/`)
execSync(`cp -r ./test-environment/routes ${dir}/`)
console.log(`Created test directory at ${dir}`)

return directory
} catch (err) {
console.error(err)
throw err
}
},
})
},
retries: {
runMode: 2,
openMode: 0,
},
},
})

async function createUniqueDirectory(): Promise<string> {
const __dirname = fileURLToPath(new URL(".", import.meta.resolve(".")))
const testdirs = path.join(__dirname, "test-environment", "testdirs")
try {
await access(testdirs, constants.F_OK)
} catch {
await mkdir(testdirs)
}
const dir = await mkdtemp(path.join(testdirs, "dir-"))
assert(typeof dir === "string")

return dir
}
8 changes: 6 additions & 2 deletions integration-tests/cypress/e2e/healthcheck.cy.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { startNeovimWithYa } from "./using-ya-to-read-events/startNeovimWithYa"

describe("the healthcheck", () => {
it("can run the :healthcheck for yazi.nvim", () => {
cy.visit("http://localhost:5173")
cy.startNeovim()
startNeovimWithYa()

// wait until text on the start screen is visible
cy.contains("If you see this text, Neovim is ready!")

cy.typeIntoTerminal(":checkhealth yazi{enter}")

// the `yazi` application should be found successfully
// the `yazi` and `ya` applications should be found successfully
cy.contains("Found yazi version 0.2.5")
cy.contains("Found ya version 0.2.5")
cy.contains("OK yazi")
})
})
Loading
Loading