dotfiles

Alpine Linux dotfiles

git clone git://git.lin.moe/dotfiles.git

  1#!/usr/bin/env python3
  2import glob
  3from pathlib import Path
  4from argparse import ArgumentParser
  5import subprocess
  6
  7current_template = {
  8    "host": "",
  9    "hostname": "",
 10    "port": "22",
 11    "user": "",
 12    "tags": [],
 13    "group": "default"
 14}
 15
 16pathes = ["~/.ssh/config"]
 17
 18def main():
 19    parser = ArgumentParser("sshhosts")
 20    parser.add_argument("-s", "--script", action='store_true', help="write script frendly output")
 21    args = parser.parse_args()
 22    
 23    global pathes
 24    hosts = dict()
 25    
 26    while len(pathes) != 0:
 27        path, pathes = pathes[0], pathes[1:]
 28        with Path(path).expanduser().open() as f:
 29            newhosts = sshhosts(f)
 30            for g, h in newhosts.items():
 31                if hosts.get(g) is None:
 32                    hosts[g] = list()
 33                hosts[g] += h
 34    
 35    output(hosts, script=args.script)
 36
 37    
 38def sshhosts(sshfile) -> dict[str, list[dict[str, any]]]:
 39    result = dict()
 40    current = current_template.copy()
 41    
 42    for line in sshfile:
 43        if len(line.strip()) == 0:
 44            continue
 45
 46        line = line.strip().lower()
 47        if line.startswith("host "):
 48
 49            if current["host"] != "":
 50                if result.get(current["group"]) is None:
 51                    result[current["group"]] = list()
 52                result[current["group"]].append(current)
 53                    
 54                current = current_template.copy()
 55
 56            parts = line.split("#", 1)
 57            if len(parts) == 1:
 58                comment = ""
 59                line = parts[0]
 60            else:
 61                (line, comment) = parts
 62
 63            options = comment.split(";")
 64            options = [i.strip() for i in options]
 65            if "hiden" in options:
 66                continue
 67            for opt in options:
 68                if opt.startswith("group:"):
 69                    current["group"] = opt[len("group:"):].strip()
 70                if opt.startswith("tags:"):
 71                    current["tags"] = [i.strip() for i in opt[len("tags:"):].strip().split(",")]
 72
 73            current["host"] = line[len("host "):]
 74            
 75        elif line.startswith("hostname "):
 76            current["hostname"] = line[len("hostname "):]
 77        elif line.startswith("port "):
 78            current["port"] = line[len("port "):]
 79        elif line.startswith("user "):
 80            current["user"] = line[len("user "):]
 81        elif line.startswith("include "):
 82            global pathes
 83            pathes += (glob.glob(str(Path(line[len("include "):]).expanduser())))
 84
 85    if current["host"] != "":
 86        if result.get(current["group"]) is None:
 87            result[current["group"]] = list()
 88        
 89        result[current["group"]].append(current)
 90
 91    return result
 92    
 93def output(hosts:dict[str, list[dict[str, any]]], script:bool = False):
 94    if script is False:
 95        for group, hosts in hosts.items(): 
 96            print(f"+ {group}")
 97            for host in hosts:
 98                prefix = f"{host['host']:15} {host['hostname']}:{host['port']}"
 99                prefix = f"{prefix:50} {'@' + host['user']if host['user'] else ''}"
100                if len(host['tags']) != 0:
101                    prefix = f"{prefix:60} {','.join(['#'+i for i in host['tags']])}"
102                print(prefix)
103            print("")
104
105    else:
106        for group, hosts in hosts.items():
107            for host in hosts:
108                prefix = f"{host['host'].strip():15} {host['hostname']}:{host['port']}{' @' + host['user']if host['user'] else ''} +{group}"
109                if len(host['tags']) != 0:
110                    prefix = f"{prefix} {','.join(['#'+i for i in host['tags']])}"
111                print(prefix)
112
113            
114
115        
116if __name__ == "__main__":
117    main()