@@ -48,6 +48,21 @@ class Target:
4848 """
4949 _ansi_re = re .compile (r'\033\[[0-9;]*m' )
5050
51+ def _pad_colored (self , colored_str , width , align = 'left' ):
52+ """Pad a colored string to a specific visible width."""
53+ visible = self ._ansi_re .sub ('' , colored_str )
54+ diff = width - len (visible )
55+ if diff <= 0 :
56+ return colored_str
57+ if align == 'right' :
58+ return ' ' * diff + colored_str
59+ elif align == 'center' :
60+ left_pad = diff // 2
61+ right_pad = diff - left_pad
62+ return ' ' * left_pad + colored_str + ' ' * right_pad
63+ else :
64+ return colored_str + ' ' * diff
65+
5166 def __init__ (self , fields ):
5267 """
5368 Initializes & stores target info based on fields.
@@ -249,7 +264,7 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
249264 decloaked_char = Color .s ('{P}*' ) if self .decloaked else ' '
250265 essid += decloaked_char
251266
252- bssid = Color .s ('{D}%s{W} ' % self .bssid ) if show_bssid else ''
267+ bssid = Color .s ('{D}%s{W}' % self .bssid ) if show_bssid else ''
253268 if show_manufacturer :
254269 oui = '' .join (self .bssid .split (':' )[:3 ])
255270 self .manufacturer = Configuration .manufacturers .get (oui , "" )
@@ -260,7 +275,7 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
260275 mfg_name = f'{ mfg_name [:max_oui_len - 3 ]} ...'
261276 else :
262277 mfg_name = mfg_name .ljust (max_oui_len )
263- manufacturer = Color .s ('{W}%s ' % mfg_name )
278+ manufacturer = Color .s ('{W}%s' % mfg_name )
264279 else :
265280 manufacturer = ''
266281
@@ -328,21 +343,44 @@ def to_str(self, show_bssid=False, show_manufacturer=False):
328343 power = f'{ pwr_bar } { Color .s ("{%s}%s" % (pwr_color , str (pwr_dbm ).rjust (2 )))} '
329344
330345 if self .wps == WPSState .UNLOCKED :
331- wps = Color .s (' {G}yes' )
346+ wps = Color .s ('{G}yes' )
332347 elif self .wps == WPSState .NONE :
333- wps = Color .s (' {D} - ' )
348+ wps = Color .s ('{D}- ' )
334349 elif self .wps == WPSState .LOCKED :
335- wps = Color .s (' {R}lck' )
350+ wps = Color .s ('{R}lck' )
336351 elif self .wps == WPSState .UNKNOWN :
337- wps = Color .s (' {O} ? ' )
352+ wps = Color .s ('{O}? ' )
338353 else :
339- wps = ' - '
354+ wps = '- '
340355
341- clients = Color .s ('{D} - ' )
342356 if len (self .clients ) > 0 :
343- clients = Color .s ('{G} %s' % str (len (self .clients )))
344-
345- result = f'{ essid } { bssid } { manufacturer } { channel } { encryption_display_string } { power } { wps } { clients } '
357+ clients = Color .s ('{G}%s' % str (len (self .clients )))
358+ else :
359+ clients = Color .s ('{D}-' )
360+
361+ # Column widths must match scanner.py header
362+ COL_ESSID = 26
363+ COL_BSSID = 19
364+ COL_MFG = 23
365+ COL_CH = 4
366+ COL_ENC = 9
367+ COL_PWR = 7
368+ COL_WPS = 5
369+ COL_CLI = 7
370+ SEP = ' '
371+
372+ parts = [self ._pad_colored (essid , COL_ESSID )]
373+ if show_bssid :
374+ parts .append (self ._pad_colored (bssid , COL_BSSID ))
375+ if show_manufacturer :
376+ parts .append (self ._pad_colored (manufacturer , COL_MFG ))
377+ parts .append (self ._pad_colored (channel , COL_CH , 'right' ))
378+ parts .append (self ._pad_colored (encryption_display_string , COL_ENC ))
379+ parts .append (self ._pad_colored (power , COL_PWR , 'right' ))
380+ parts .append (self ._pad_colored (wps , COL_WPS , 'center' ))
381+ parts .append (self ._pad_colored (clients , COL_CLI , 'right' ))
382+
383+ result = SEP .join (parts )
346384
347385 result += Color .s ('{W}' )
348386 return result
0 commit comments