1 #include <msp/core/algorithm.h>
2 #include <msp/core/application.h>
3 #include <msp/core/getopt.h>
4 #include <msp/fs/dir.h>
5 #include <msp/fs/stat.h>
6 #include <msp/fs/utils.h>
7 #include <msp/io/print.h>
8 #include <msp/time/datetime.h>
13 class Ls: public RegisteredApplication<Ls>
16 typedef vector<string> Row;
26 Row create_row(const string &, const FS::Stat &);
27 void print_rows(const vector<Row> &);
30 Ls::Ls(int argc, char **argv):
34 getopt.add_option('l', "long", long_format, GetOpt::NO_ARG);
35 getopt.add_argument("file", args, GetOpt::OPTIONAL_ARG);
44 vector<Row> file_rows;
46 for(const string &a: args)
49 FS::Stat stat = FS::lstat(path);
50 if(stat.is_directory())
53 vector<string> files = FS::list_files(path);
55 for(const string &fn: files)
58 rows.push_back(create_row(fn, FS::lstat(path/fn)));
70 IO::print("%s:\n", a);
76 file_rows.push_back(create_row(a, stat));
81 file_rows.push_back(r);
85 if(!file_rows.empty())
89 print_rows(file_rows);
95 Ls::Row Ls::create_row(const string &name, const FS::Stat &st)
99 result.push_back("-");
100 else if(st.is_directory())
101 result.push_back("D");
102 else if(st.is_symlink())
103 result.push_back("L");
105 result.push_back("?");
107 result.push_back(st.get_owner());
108 result.push_back(st.get_group());
109 result.push_back(format("%d", st.get_size()));
110 result.push_back(Time::DateTime(st.get_modify_time()).format("%Y-%m-%d %H:%M:%S"));
111 result.push_back(name);
116 void Ls::print_rows(const vector<Row> &rows)
118 vector<unsigned> col_width;
120 for(const Row &row: rows)
122 if(row.size()>col_width.size())
123 col_width.resize(row.size(), 0);
124 for(unsigned j=0; j<row.size(); ++j)
125 col_width[j] = max<unsigned>(col_width[j], row[j].size());
128 for(const Row &row: rows)
131 for(unsigned j=0; j<row.size(); ++j)
135 unsigned padding = col_width[j]-row[j].size();
137 line += string(padding, ' ');
140 line += string(padding, ' ');