Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Better ls implementation #50

Merged
merged 2 commits into from
Feb 7, 2023
Merged

Better ls implementation #50

merged 2 commits into from
Feb 7, 2023

Conversation

MarcoCicognani
Copy link
Contributor

No description provided.

Copy link
Owner

@byteduck byteduck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for giving ls a much-needed facelift, it looks great! I've never seen permission colorization before, it's a really cool idea :)

I suggested a few changes, nothing major. I think that we would ideally hide file sizes, permission colorization, and human readable / raw sizes behind option flags, but there's no need to worry about that in this PR for now. Thanks again!

args.add_named(colorize, std::nullopt, "color", "Colorize the output.");
args.add_named(show_all, "a", "all", "Show entries starting with \".\".");
args.add_positional(g_dir_name, false, "DIR", "The directory to list.");
args.add_named(g_no_color, "n", "no-color", "Do not g_colorize the output.");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
args.add_named(g_no_color, "n", "no-color", "Do not g_colorize the output.");
args.add_named(g_no_color, "n", "no-color", "Do not colorize the output.");

Accidental find+replace mishap :)

Comment on lines 28 to 167
}
s += '-';
}
return s;
}

static std::string entry_permissions_string(mode_t mode, bool colorize) {
std::string s;
s += entry_permission_string(mode, S_IRUSR, colorize ? R_FORMAT : nullptr, 'r');
s += entry_permission_string(mode, S_IWUSR, colorize ? W_FORMAT : nullptr, 'w');
s += entry_permission_string(mode, S_IXUSR, colorize ? X_FORMAT : nullptr, 'x');
s += entry_permission_string(mode, S_IRGRP, colorize ? R_FORMAT : nullptr, 'r');
s += entry_permission_string(mode, S_IWGRP, colorize ? W_FORMAT : nullptr, 'w');
s += entry_permission_string(mode, S_IXGRP, colorize ? X_FORMAT : nullptr, 'x');
s += entry_permission_string(mode, S_IROTH, colorize ? R_FORMAT : nullptr, 'r');
s += entry_permission_string(mode, S_IWOTH, colorize ? W_FORMAT : nullptr, 'w');
s += entry_permission_string(mode, S_IXOTH, colorize ? X_FORMAT : nullptr, 'x');
return s;
}

static std::string entry_fmt_size(Duck::DirectoryEntry::Type d_type, off_t size) {
std::stringstream ss;
if(d_type == Duck::DirectoryEntry::REGULAR) {
char mul = ' ';
if(size >= 1024 * 1024 * 1024) {
mul = 'G';
size /= 1024 * 1024 * 1024;
} else if(size >= 1024 * 1024) {
mul = 'M';
size /= 1024 * 1024;
} else if(size >= 1024) {
mul = 'K';
size /= 1024;
}
ss << std::right << std::setw(4) << size << mul;
} else {
ss << std::right << std::setw(4) << '-' << ' ';
}
return ss.str();
}

static std::string entry_name(std::string const& name, Duck::DirectoryEntry::Type d_type, bool colorize) {
std::string s;
if(colorize) {
switch(d_type) {
case DirectoryEntry::UNKNOWN:
break;
case DirectoryEntry::REGULAR:
s += REG_FORMAT;
break;
case DirectoryEntry::DIRECTORY:
s += DIR_FORMAT;
break;
case DirectoryEntry::CHARDEVICE:
s += CHR_FORMAT;
break;
case DirectoryEntry::BLOCKDEVICE:
s += BLK_FORMAT;
break;
case DirectoryEntry::FIFO:
s += FIFO_FORMAT;
break;
case DirectoryEntry::SOCKET:
s += SOCK_FORMAT;
break;
case DirectoryEntry::SYMLINK:
s += LNK_FORMAT;
break;
}
}

s += name;

if(colorize) {
s += RESET_FORMAT;
}
return s;
}

DirectoryEntry::DirectoryEntry(const Path& parent_path, const struct dirent* entry) :
m_path(parent_path / entry->d_name), m_inode(entry->d_ino), m_type((Type) entry->d_type),
m_name(entry->d_name) {
struct stat st;
stat(m_path.string().c_str(), &st);
m_size = st.st_size;
m_mode = st.st_mode;
}

std::string DirectoryEntry::as_fmt_string(bool colorize) const {
std::stringstream ss;
ss << entry_type_char(m_type)
<< ' '
<< entry_permissions_string(m_mode, colorize)
<< ' '
<< entry_fmt_size(m_type, m_size)
<< ' '
<< entry_name(m_name, m_type, colorize);
return ss.str();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, I think this sort of logic dealing with formatting directory entries with colors and such should stay in ls.cpp, since I don't see it being super useful elsewhere for now. If necessary in the future, we could extract it to another utility class, but I don't think it belongs in DirectoryEntry for now.

Comment on lines 89 to 95
std::sort(entries.begin(), entries.end(), [](auto const& lhs, auto const& rhs) {
return lhs.name() < rhs.name();
});
std::sort(entries.begin(), entries.end(), [](auto const& lhs, auto const& rhs) {
return lhs.type() > rhs.type();
});

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if we should be sorting directory entries by default - this could incur unnecessary performance costs when iterating over directories where sorting isn't important. I think we should probably extract this logic to ls.cpp for now.

What we could do is override operator< for DirectoryEntry so that it's easier to just call std::sort on it without writing a custom comparison function.

Comment on lines 89 to 108
std::stringstream ss;
if(d_type == Duck::DirectoryEntry::REGULAR) {
char mul = ' ';
if(size >= 1024 * 1024 * 1024) {
mul = 'G';
size /= 1024 * 1024 * 1024;
} else if(size >= 1024 * 1024) {
mul = 'M';
size /= 1024 * 1024;
} else if(size >= 1024) {
mul = 'K';
size /= 1024;
}
ss << std::right << std::setw(4) << size << mul;
} else {
ss << std::right << std::setw(4) << '-' << ' ';
}
return ss.str();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's actually logic for this sort of thing in Memory::Amount in libsys, although that is technically for memory and not storage sizes (not that it makes a ton of difference). We can leave this for now, but I think later I'll make a general utility class for formatting sizes like this

@MarcoCicognani
Copy link
Contributor Author

MarcoCicognani commented Feb 7, 2023

I moved the logic from DirectoryEntry.cpp to ls.cpp and the sort from Path.cpp to ls.cpp, as you asked.

@MarcoCicognani
Copy link
Contributor Author

MarcoCicognani commented Feb 7, 2023

I personally use exa as ls replacement, I took the idea for permissions color from it.

@byteduck byteduck merged commit 0905851 into byteduck:master Feb 7, 2023
@byteduck
Copy link
Owner

byteduck commented Feb 7, 2023

Looks good, thank you! Merged :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants