0

I am trying to write a terminal emulator in a react app, for a personal coding website. I'm trying to create basic functionality, namely 'pwd', 'ls', 'cat' and 'cd'. I have a react component that does all the work for the file explorer, which is basically used to keep track of the current folder. Here is the code:

import React, { useState } from 'react';

const FileExplorer = () => {
  const [currentDirectory, setCurrentDirectory] = useState('/home/user');
  const [fileContents, setFileContents] = useState({
    '/home/user/file1.txt': 'Content of file1.txt',
    '/home/user/file2.txt': 'Content of file2.txt',
    '/home/user/folder1': {
      '/home/user/file3.txt': 'Content of file3.txt',
    },
  });

  const [parentDirectory, setParentDirectory] = useState(null);

  const getCurrentDirectoryContents = () => {
    return listDirectory(currentDirectory);
  };

  const listDirectory = (directory) => {
    const entries = Object.keys(fileContents);
    const currentDirectoryEntries = entries.filter((path) =>
      path.startsWith(directory)
    );

    console.log('Current Directory Entries:', currentDirectoryEntries);

    const subdirectoryEntries = currentDirectoryEntries.filter(
      (path) => typeof fileContents[path] === 'object'
    );
    subdirectoryEntries.forEach((subdirectory) => {
      const subdirectoryPath = subdirectory + '/';
      const subdirectoryContents = listDirectory(subdirectoryPath);
      currentDirectoryEntries.push(...subdirectoryContents);
    });

    return currentDirectoryEntries;
  };

  const changeDirectory = (newDirectory) => {
    if (newDirectory === '..') {
      if (parentDirectory) {
        setCurrentDirectory(parentDirectory);
        setParentDirectory(null);
      } else {
        return 'cd: ../: No such file or directory';
      }
    } else if (newDirectory.startsWith('/')) {
      if (fileContents[newDirectory] && typeof fileContents[newDirectory] === 'object') {
        setParentDirectory(currentDirectory);
        setCurrentDirectory(newDirectory);
      } else {
        return `cd: ${newDirectory}: Not a directory`;
      }
    } else {
      const newPath = currentDirectory + '/' + newDirectory;
      if (fileContents[newPath] && typeof fileContents[newPath] === 'object') {
        setParentDirectory(currentDirectory);
        setCurrentDirectory(newPath);
      } else {
        return `cd: ${newDirectory}: Not a directory`;
      }
    }
  };

  const readFile = (filePath) => {
    if (filePath.startsWith('/')) {
      if (fileContents[filePath]) {
        return fileContents[filePath];
      } else {
        return `cat: ${filePath}: No such file or directory`;
      }
    } else {
      const fullPath = currentDirectory + '/' + filePath;
      if (fileContents[fullPath]) {
        return fileContents[fullPath];
      } else {
        return `cat: ${filePath}: No such file or directory`;
      }
    }
  };

  const ls = () => {
    const currentDirContents = getCurrentDirectoryContents();
    const relativePaths = currentDirContents.map((path) =>
      path.substring(currentDirectory.length)
    );
    return relativePaths.join(' ');
  };

  return { currentDirectory, getCurrentDirectoryContents, changeDirectory, readFile, ls };
};

export default FileExplorer;

The issue is, when I 'cd' into folder1, the file directory knows it's in folder1 (pwd returns /home/user/folder1) but when I type 'ls', it does not print out that file3 is in the folder. Nor can I 'open' file3 using the cat command like I can the files in the root folders. What am I doing wrong here?

I've tried changing the folder structure around, and changing some of the functions, but no avail.

5
  • Does it matter that your "file3.txt" seems to be at the same level as the folder it's supposed to be in? (both in the /home/user directory) Commented Dec 23, 2023 at 23:36
  • @JamesHearn hmm ok, so what would you suggest I do? where should I put the file instead? I'm not sure if that's the issue, or how I choose to create my folder/file structure Edit: i changed the path to '/home/user/folder1/file3.txt' and still not showing up in ls Commented Dec 23, 2023 at 23:39
  • Does the console.log in the listDirectory function log what you'd expect when using ls? Presumably /home/user/folder1? Commented Dec 24, 2023 at 0:02
  • Yep, that works. It recognizes that it's in the /home/user/folder1 directory. Small update: I'm trying to do this, const [fileContents, setFileContents] = useState({ '/home/user/file1.txt': 'Content of file1.txt', '/home/user/file2.txt': 'Content of file2.txt', '/home/user/folder1': {}, // empty object for the folder '/home/user/folder1/file3.txt': 'Content of file3.txt', }); and now I see '/home/user/folder1/file3.txt' twice in the root folder, and /file3.txt twice in the folder1 folder. Commented Dec 24, 2023 at 0:08
  • I think essentially the root of the issue is within the listDirectory function: I think there is a recursive issue, as you call the function from within itself - this would explain the duplication of results with your new structure. Beyond that, I don't believe the manipulation of the arrays with .filter and .forEach etc is having the desired effect. It's difficult for me to tell without the whole app, but I suspect the genesis of the problem is there. I would recommend doing some detailed console.log - ing at each step to make sure you are manipulating the data you are expecting. Commented Dec 24, 2023 at 0:19

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.