Reputation: 479
I'm trying to replicate the ls function in bash with columns like this:
I tried .format to add padding to the file names but im still not getting the desired output the last column overflows everytime.
def show_dirs():
filelist = os.listdir(os.getcwd())
filelist.sort()
scr_width = int(os.popen("stty size", "r").read().split()[1])
max_len = -1
for file_len in filelist:
if len(file_len) > max_len and scr_width > max_len*2:
max_len = len(file_len)
mlen = max_len #+ 1
print(color["cyan"] + "Files in the current directory")
if scr_width < mlen:
mlen = scr_width
line = ""
for count, _file in enumerate(filelist):
if os.path.isdir(_file):
_file = _file + os.sep
st = "[{0:>2}] {1:<{mlen}}".format(str(count + 1), _file, mlen=mlen)
if len(line) % scr_width > len(st):
line = line + color["green"] + st
else:
line = line + "\n" + color["green"] + st
else:
st = "[{0:>2}] {1:<{mlen}}".format(str(count + 1), _file, mlen=mlen)
if len(line) % scr_width > len(st):
line = line + color["cyan"] + st
else:
line = line + "\n" + color["cyan"] + st
print(line)
I get this output:
Upvotes: 1
Views: 148
Reputation: 479
I improved my algorithm and now it works fine when the terminal size is fixed
color = {
"red": "\033[31m",
"green": "\033[32m",
"orange": "\033[33m",
"purple": "\033[35m",
"cyan": "\033[36m",
"yellow": "\033[93m",
}
def show_dirs(path=os.getcwd()):
print(color["cyan"] + "Files in the current directory")
filelist = os.listdir(path)
filelist.sort()
#index padding
ind = len(filelist)
if ind >= 1000:
ind = 4
elif ind >= 100:
ind = 3
elif ind >= 10:
ind = 2
else:
ind = 1
scr_width = int(os.get_terminal_size()[0]) #terminal width
mlen = max(len(word) for word in filelist) + 1 #column width
cols = scr_width // mlen #possible columns
if scr_width < mlen:
mlen = scr_width
line = ""
lst = []
for count, _file in enumerate(filelist, start=1):
if os.path.isdir(_file):
_file = _file + os.sep
st = "[{0:>{ind}}] {1:<{mlen}}".format(
str(count), _file, mlen=mlen, ind=ind
)
if scr_width - ((len(line) - cols * 5) % scr_width) > len(st): # - cols * 5 to compensate the length of color codes
line = line + color["cyan"] + st
else:
lst.append(line)
line = color["cyan"] + st
else:
st = "[{0:>{ind}}] {1:<{mlen}}".format(
str(count), _file, mlen=mlen, ind=ind
)
if scr_width - ((len(line) - cols * 5) % scr_width) > len(st): # - cols * 5 to compensate the length of color codes
line = line + color["green"] + st
else:
lst.append(line)
line = color["green"] + st
if lst == []:
lst.append(line)
print("\n".join(lst))
Upvotes: 0
Reputation: 2055
So, it turns out that column output of a list of arbitrary strings is done by the Linux column command. One option is to assume the existence of this command on your system (it exists in my environment) and to use it as an out-of-process output filter.
Another option is to dig deeper into the source code of columns
, and reimplement it in Python, possibly as a generator function. I found a pointer in GitHub. Note that this is over 800 lines of C code.
You can also create Python binding for the core functionality of that C code, which would yield a better performing code. Sadly I do not have experience with integrating C code into Python.
If you decide to opt for the second alternative, you can post your implementation as an answer here.
Upvotes: 1