Skip to content

Commit

Permalink
fix spaces at end of line issue. Add Z option
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-ward committed Jul 7, 2024
1 parent df08b42 commit 2841b87
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 53 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@

All notable changes to this project will be documented in this file.

### [2024.3] 2024-07-05
## [2024.4] - 2024-07-07
### Added
- Optionally (-Z) truncate lines if too long. Show `` to indicate truncation
- Minor performnce tweaks

### Fixed
- remove end-of-line padding when no borders specfied #1
- fix date minute formatting error

## [2024.3] - 2024-07-05
### Added
- file icons

Expand Down
15 changes: 12 additions & 3 deletions lsv/entry.v
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@ fn get_entries(files []string, options Options) []Entry {
for file in files {
if os.is_dir(file) {
dir_files := os.ls(file) or { continue }
entries << dir_files.map(make_entry(it, file, options))
continue
entries << match options.all {
true { dir_files.map(make_entry(it, file, options)) }
else { dir_files.filter(!is_dot_file(it)).map(make_entry(it, file, options)) }
}
} else {
if options.all || !is_dot_file(file) {
entries << make_entry(file, '', options)
}
}
entries << make_entry(file, '', options)
}
return entries
}
Expand Down Expand Up @@ -146,3 +151,7 @@ fn checksum(name string, dir_name string, options Options) string {
// vfmt on
}
}

fn is_dot_file(file string) bool {
return file.len > 0 && file[0] == `.`
}
20 changes: 6 additions & 14 deletions lsv/filter.v
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
fn filter(entries []Entry, options Options) []Entry {
mut filtered := entries.clone()

if !options.all {
filtered = entries.filter(it.name.starts_with('../') || !it.name.starts_with('.'))
return match true {
// vfmt off
options.only_dirs { entries.clone().filter(it.dir) }
options.only_files { entries.clone().filter(it.file) }
else { entries }
// vfmt on
}

if options.only_dirs {
filtered = filtered.filter(it.dir)
}

if options.only_files {
filtered = filtered.filter(it.file)
}

return filtered
}
30 changes: 18 additions & 12 deletions lsv/format.v
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import arrays
import os
import strings
import term
import v.mathutil
import os

const cell_max = 12 // limit on wide displays
const cell_spacing = 3 // space between cells
Expand All @@ -12,7 +12,7 @@ enum Align {
right
}

fn format(entries []Entry, options Options) {
fn print_files(entries []Entry, options Options) {
w, _ := term.get_terminal_size()
options_width_ok := options.width_in_cols > 0 && options.width_in_cols < 1000
width := if options_width_ok { options.width_in_cols } else { w }
Expand All @@ -35,7 +35,6 @@ fn format_by_cells(entries []Entry, width int, options Options) {
partial_row := entries.len % max_cols != 0
rows := entries.len / max_cols + if partial_row { 1 } else { 0 }
max_rows := mathutil.max(1, rows)
mut line := strings.new_builder(200)

for r := 0; r < max_rows; r += 1 {
for c := 0; c < max_cols; c += 1 {
Expand All @@ -44,30 +43,27 @@ fn format_by_cells(entries []Entry, width int, options Options) {
entry := entries[idx]
name := format_entry_name(entry, options)
cell := format_cell(name, len, .left, get_style_for(entry, options), options)
line.write_string(cell)
print(cell)
}
}
println(line)
print_newline()
}
}

fn format_by_lines(entries []Entry, width int, options Options) {
len := entries.max_name_len(options) + cell_spacing
cols := mathutil.min(width / len, cell_max)
max_cols := mathutil.max(cols, 1)
mut line := strings.new_builder(200)

for i, entry in entries {
if i % max_cols == 0 && i != 0 {
println(line)
print_newline()
}
name := format_entry_name(entry, options)
cell := format_cell(name, len, .left, get_style_for(entry, options), options)
line.write_string(cell)
}
if entries.len % max_cols != 0 {
println(line)
print(cell)
}
print_newline()
}

fn format_one_per_line(entries []Entry, options Options) {
Expand Down Expand Up @@ -123,7 +119,7 @@ fn format_table_cell(s string, width int, align Align, style Style, options Opti
// surrounds a cell with table borders
fn print_dir_name(name string, options Options) {
if name.len > 0 {
print('\n')
print_newline()
nm := if options.colorize { style_string(name, options.style_di, options) } else { name }
println('${nm}:')
}
Expand Down Expand Up @@ -209,3 +205,13 @@ fn format_entry_name(entry Entry, options Options) string {
fn real_length(s string) int {
return term.strip_ansi(s).runes().len
}

@[inline]
fn print_space() {
print_character(` `)
}

@[inline]
fn print_newline() {
print_character(`\n`)
}
57 changes: 37 additions & 20 deletions lsv/format_long.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import arrays
import os
import term
import time
import v.mathutil { max }

Expand Down Expand Up @@ -41,6 +42,7 @@ fn format_long_listing(entries []Entry, options Options) {
longest := longest_entries(entries, options)
header, cols := format_header(options, longest)
header_len := real_length(header)
term_cols, _ := term.get_terminal_size()

print_header(header, options, header_len, cols)
print_header_border(options, header_len, cols)
Expand All @@ -53,7 +55,7 @@ fn format_long_listing(entries []Entry, options Options) {
if idx % block_size == 0 && idx != 0 {
match options.table_format {
true { print(border_row_middle(header_len, cols)) }
else { print('\n') }
else { print_newline() }
}
}
}
Expand All @@ -67,53 +69,53 @@ fn format_long_listing(entries []Entry, options Options) {
if options.inode {
content := if entry.invalid { unknown } else { entry.stat.inode.str() }
print(format_cell(content, longest.inode, Align.right, no_style, options))
print(space)
print_space()
}

// checksum
if options.checksum != '' {
checksum := format_cell(entry.checksum, longest.checksum, .left, dim, options)
print(checksum)
print(space)
print_space()
}

// permissions
if !options.no_permissions {
flag := file_flag(entry, options)
print(format_cell(flag, 1, .left, no_style, options))
print(space)
print_space()

content := permissions(entry, options)
print(format_cell(content, permissions_title.len, .right, no_style, options))
print(space)
print_space()
}

// octal permissions
if options.octal_permissions {
content := format_octal_permissions(entry, options)
print(format_cell(content, 4, .left, dim, options))
print(space)
print_space()
}

// hard links
if !options.no_hard_links {
content := if entry.invalid { unknown } else { '${entry.stat.nlink}' }
print(format_cell(content, longest.nlink, .right, dim, options))
print(space)
print_space()
}

// owner name
if !options.no_owner_name {
content := if entry.invalid { unknown } else { get_owner_name(entry.stat.uid) }
print(format_cell(content, longest.owner_name, .right, dim, options))
print(space)
print_space()
}

// group name
if !options.no_group_name {
content := if entry.invalid { unknown } else { get_group_name(entry.stat.gid) }
print(format_cell(content, longest.group_name, .right, dim, options))
print(space)
print_space()
}

// size
Expand All @@ -133,31 +135,46 @@ fn format_long_listing(entries []Entry, options Options) {
}
size := format_cell(content, longest.size, .right, size_style, options)
print(size)
print(space)
print_space()
}

// date/time(modified)
if !options.no_date {
print(format_time(entry, .modified, options))
print(space)
print_space()
}

// date/time (accessed)
if options.accessed_date {
print(format_time(entry, .accessed, options))
print(space)
print_space()
}

// date/time (status change)
if options.changed_date {
print(format_time(entry, .changed, options))
print(space)
print_space()
}

// file name
file_name := format_entry_name(entry, options)
file_style := get_style_for(entry, options)
println(format_cell(file_name, longest.file, .left, file_style, options))
match options.table_format {
true { print(format_cell(file_name, longest.file, .left, file_style, options)) }
else { print(format_cell(file_name, 0, .left, file_style, options)) }
}

// line too long? Print a '≈' in the last column
if options.no_wrap {
mut coord := term.get_cursor_position() or { term.Coord{} }
if coord.x >= term_cols {
coord.x = term_cols
term.set_cursor_position(coord)
print('≈')
}
}

print_newline()
}

// bottom border
Expand Down Expand Up @@ -267,12 +284,12 @@ fn format_header(options Options, longest Longest) (string, []int) {
}

fn time_format(options Options) string {
return if options.time_iso {
date_iso_format
} else if options.time_compact {
date_compact_format
} else {
date_format
return match true {
// vfmt off
options.time_iso { date_iso_format }
options.time_compact { date_compact_format }
else { date_format }
// vfmt on
}
}

Expand Down
1 change: 1 addition & 0 deletions lsv/icons.v
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ const icons_map = {
'ts': '󰛦'
'twig': '\ue61c'
'txt': '\uf15c'
'v': '𝕍'
'vagrantfile': '\ue21e'
'video': '\uf03d'
'vim': '\ue62b'
Expand Down
23 changes: 21 additions & 2 deletions lsv/lsv.v
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import os

fn main() {
options := parse_args(os.args)
set_auto_wrap(options)
entries := get_entries(options.files, options)
mut cyclic := Set[string]{}
lsv(entries, options, mut cyclic)
Expand All @@ -22,12 +23,12 @@ fn lsv(entries []Entry, options Options, mut cyclic Set[string]) {
if group_by_dirs.len > 1 || options.recursive {
print_dir_name(dir, options)
}
format(sorted, options)
print_files(sorted, options)

if options.recursive {
for entry in sorted {
entry_path := os.join_path(entry.dir_name, entry.name)
if entry.dir {
entry_path := os.join_path(entry.dir_name, entry.name)
if cyclic.exists(entry_path) {
println('===> cyclic reference detected <===')
continue
Expand All @@ -41,3 +42,21 @@ fn lsv(entries []Entry, options Options, mut cyclic Set[string]) {
}
}
}

fn set_auto_wrap(options Options) {
if options.no_wrap {
wrap_off := '\e[?7l'
wrap_reset := '\e[?7h'
println(wrap_off)

at_exit(fn [wrap_reset] () {
println(wrap_reset)
}) or {}

// Ctrl-C handler
os.signal_opt(os.Signal.int, fn (sig os.Signal) {
println('\e[?7h') // until compile bug fixed
exit(0)
}) or {}
}
}
5 changes: 4 additions & 1 deletion lsv/options.v
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct Options {
width_in_cols int
with_commas bool
icons bool
no_wrap bool
//
// filter, group and sorting options
all bool
Expand Down Expand Up @@ -74,7 +75,7 @@ fn parse_args(args []string) Options {
mut fp := flag.new_flag_parser(args)

fp.application(app_name)
fp.version('2024.3')
fp.version('2024.4')
fp.skip_executable()
fp.description('List information about FILES')
fp.arguments_description('[FILES]')
Expand All @@ -88,6 +89,7 @@ fn parse_args(args []string) Options {
recursive := fp.bool('', `R`, false, 'list subdirectories recursively')
recursion_depth := fp.int('depth', ` `, max_int, 'limit depth of recursion')
list_by_lines := fp.bool('', `X`, false, 'list files by lines instead of by columns')
no_wrap := fp.bool('', `Z`, false, 'do not wrap long lines')
one_per_line := fp.bool('', `1`, false, 'list one file per line')

width_in_cols := fp.int('width', ` `, 0, 'set output width to <int>\n\nFiltering and Sorting Options:')
Expand Down Expand Up @@ -159,6 +161,7 @@ fn parse_args(args []string) Options {
no_owner_name: no_owner_name
no_permissions: no_permissions
no_size: no_size
no_wrap: no_wrap
octal_permissions: octal_permissions
one_per_line: one_per_line
only_dirs: only_dirs
Expand Down

0 comments on commit 2841b87

Please sign in to comment.