def _pick_color_interactive(templater: Templater, host_cfg: hostconfig.HostConfig, flag: str) -> str: '''Picks a color and maybe prompts based on current state.''' return flag or templater.get_color() or click.prompt( 'Select a color', default=host_cfg.default_color, type=click.Choice(templater.list_colors()))
def test_list_themes_path_nonexistent_raises(self): '''Test listing the available themes when the dir does not exist.''' themes_path = Path(self.theme_dir.name) / Path('dne') host_config = HostConfig(themes_path, None) templater = Templater(Path(self.link_dir.name), host_config) with self.assertRaises(FileNotFoundError): templater.list_themes()
def set_color(name: str): '''Set the color to NAME and redeploy.''' host_cfg = hostconfig.from_file(ACTIVE_HOST_PATH) templater = Templater(MODOT_PATH, host_cfg) if name not in templater.list_colors(): sys.exit(f'Could not find specified color {name}') templater.set_color(name) _check_and_deploy(host_cfg, templater, dryrun=False)
def test_get_theme_not_a_link_raises(self): '''Test getting theme when the active path isn't a link.''' link_path = Path(self.link_dir.name) theme_link_path = Path(self.link_dir.name) / Path('theme.yaml') theme_link_path.touch() templater = Templater(link_path) with self.assertRaises(LinkMalformedError): templater.get_theme()
def test_list_colors(self): '''Test listing the available colors.''' colors_path = Path(self.color_dir.name) (colors_path / Path('coolcolor.yaml')).touch() (colors_path / Path('radcolor.yaml')).touch() host_config = HostConfig(None, colors_path) templater = Templater(Path(self.link_dir.name), host_config) self.assertCountEqual(templater.list_colors(), ['coolcolor', 'radcolor'])
def test_get_color(self): '''Test getting color with a correctly formatted link.''' link_path = Path(self.link_dir.name) color_link_path = Path(self.link_dir.name) / Path('color.yaml') color_tgt_path = Path(self.color_dir.name) / Path('coolcolor.yaml') color_tgt_path.touch() color_link_path.symlink_to(color_tgt_path) templater = Templater(link_path) self.assertEqual(templater.get_color(), 'coolcolor')
def test_get_theme(self): '''Test getting theme with a correctly formatted link.''' link_path = Path(self.link_dir.name) theme_link_path = Path(self.link_dir.name) / Path('theme.yaml') theme_tgt_path = Path(self.theme_dir.name) / Path('cooltheme.yaml') theme_tgt_path.touch() theme_link_path.symlink_to(theme_tgt_path) templater = Templater(link_path) self.assertEqual(templater.get_theme(), 'cooltheme')
def test_list_themes(self): '''Test listing the available themes.''' themes_path = Path(self.theme_dir.name) (themes_path / Path('cooltheme.yaml')).touch() (themes_path / Path('radtheme.yaml')).touch() host_config = HostConfig(themes_path, None) templater = Templater(Path(self.link_dir.name), host_config) self.assertCountEqual(templater.list_themes(), ['cooltheme', 'radtheme'])
def test_set_theme(self): '''Test setting the active theme.''' host_config = HostConfig(Path(self.theme_dir.name), None) templater = Templater(Path(self.link_dir.name), host_config) templater.set_theme('cooltheme') active_theme_path = Path(self.link_dir.name) / 'theme.yaml' self.assertEqual( # this is maybe questionable Path(os.readlink(active_theme_path)), Path(self.theme_dir.name) / 'cooltheme.yaml')
def test_set_color(self): '''Test setting the active color.''' host_config = HostConfig(Path(self.color_dir.name), Path(self.color_dir.name)) templater = Templater(Path(self.link_dir.name), host_config) templater.set_color('coolcolor') active_color_path = Path(self.link_dir.name) / 'color.yaml' self.assertEqual( # this is maybe questionable Path(os.readlink(active_color_path)), Path(self.color_dir.name) / 'coolcolor.yaml')
def test_get_color_link_malformed_raises(self): '''Test getting color from a malformed link target name.''' link_path = Path(self.link_dir.name) color_link_path = Path(self.link_dir.name) / Path('color.yaml') color_tgt_path = Path(self.color_dir.name) / Path('notyaml.txt') color_tgt_path.touch() color_link_path.symlink_to(color_tgt_path) templater = Templater(link_path) with self.assertRaises(LinkMalformedError): templater.get_color()
def test_get_theme_link_tgt_malformed_raises(self): '''Test getting theme from a malformed link target name.''' link_path = Path(self.link_dir.name) theme_link_path = Path(self.link_dir.name) / Path('theme.yaml') theme_tgt_path = Path(self.theme_dir.name) / Path('notyaml.txt') theme_tgt_path.touch() theme_link_path.symlink_to(theme_tgt_path) templater = Templater(link_path) with self.assertRaises(LinkMalformedError): templater.get_theme()
def test_template_conf_dne(self): '''Test templating a string.''' theme_path = self.theme_dir / 'main.yaml' color_path = self.color_dir / 'main.yaml' (self.link_dir / 'theme.yaml').symlink_to(theme_path) (self.link_dir / 'color.yaml').symlink_to(color_path) theme_path.write_text('theme: cooltheme') host_cfg = HostConfig(self.theme_dir, self.color_dir) templater = Templater(self.link_dir, host_cfg) with self.assertRaises(LinkMalformedError): templater.template('theme: {{theme}}\ncolor: {{color}}')
def test_template(self): '''Test templating a string.''' theme_path = self.theme_dir / 'main.yaml' color_path = self.color_dir / 'main.yaml' (self.link_dir / 'theme.yaml').symlink_to(theme_path) (self.link_dir / 'color.yaml').symlink_to(color_path) theme_path.write_text('theme: cooltheme') color_path.write_text('color: coolcolor') host_cfg = HostConfig(self.theme_dir, self.color_dir) templater = Templater(self.link_dir, host_cfg) out_str = templater.template('theme: {{theme}}\ncolor: {{color}}') self.assertEqual(out_str, 'theme: cooltheme\ncolor: coolcolor')
def get_theme(): '''Print the currently deployed theme.''' deployed_theme = Templater(MODOT_PATH).get_theme() if deployed_theme: print(deployed_theme) else: sys.exit('No theme currently deployed')
def get_color(): '''Print the currently deployed color.''' deployed_color = Templater(MODOT_PATH).get_color() if deployed_color: print(deployed_color) else: sys.exit('No color currently deployed')
def cli(ctx: click.Context): '''Modular dotfile manager. Run without a command for a summary of current state. ''' MODOT_PATH.mkdir(exist_ok=True, parents=True) if ctx.invoked_subcommand is None: host = hostconfig.get_deployed_host(ACTIVE_HOST_PATH) print(f'Deployed: {str(host)}' if host else 'No deployed host config') templater = Templater(MODOT_PATH) deployed_theme = templater.get_theme() print(f'Deployed theme: {deployed_theme}' if deployed_theme else 'No deployed theme') deployed_color = templater.get_color() print(f'Deployed color: {deployed_color}' if deployed_color else 'No deployed color') print('--help for usage')
def deploy(host: str, theme_flag: str, color_flag: str, interactive: bool, dryrun: bool): '''Configure and deploy dotfiles using configuration from HOST.''' host_path = Path(host) deployed_host_tgt = hostconfig.get_deployed_host(ACTIVE_HOST_PATH) if deployed_host_tgt: if deployed_host_tgt == host_path: print(f'Redeploying same host: {str(deployed_host_tgt)}') else: ACTIVE_HOST_PATH.unlink() ACTIVE_HOST_PATH.symlink_to(host_path) print(f'Deploying over old host: {str(deployed_host_tgt)}') else: print('Deploying host config: ' + str(host_path)) ACTIVE_HOST_PATH.symlink_to(host_path) host_cfg = hostconfig.from_file(ACTIVE_HOST_PATH) templater = Templater(MODOT_PATH, host_cfg) if interactive: theme_name = _pick_theme_interactive(templater, host_cfg, theme_flag) color_name = _pick_color_interactive(templater, host_cfg, color_flag) else: theme_name = _pick_theme_noninteractive(templater, host_cfg, theme_flag) color_name = _pick_color_noninteractive(templater, host_cfg, color_flag) templater.set_theme(theme_name) templater.set_color(color_name) _check_and_deploy(host_cfg, templater, dryrun)
def test_template_after_set_color(self): '''Test that set_color changes the output even after first use.''' theme_path = self.theme_dir / 'main.yaml' color_path = self.color_dir / 'main.yaml' new_color_path = self.color_dir / 'new.yaml' (self.link_dir / 'theme.yaml').symlink_to(theme_path) (self.link_dir / 'color.yaml').symlink_to(color_path) theme_path.write_text('theme: cooltheme') color_path.write_text('color: coolcolor') new_color_path.write_text('color: newcolor') host_cfg = HostConfig(self.theme_dir, self.color_dir) templater = Templater(self.link_dir, host_cfg) templater.template('theme: {{theme}}\ncolor: {{color}}') templater.set_color('new') out_str = templater.template('theme: {{theme}}\ncolor: {{color}}') self.assertEqual(out_str, 'theme: cooltheme\ncolor: newcolor')
def test_list_colors_dir_empty(self): '''Test listing the colors with none available.''' colors_path = Path(self.color_dir.name) host_config = HostConfig(None, colors_path) templater = Templater(Path(self.link_dir.name), host_config) self.assertCountEqual(templater.list_colors(), [])
def test_list_themes_dir_empty(self): '''Test listing the themes with none available.''' themes_path = Path(self.theme_dir.name) host_config = HostConfig(themes_path, None) templater = Templater(Path(self.link_dir.name), host_config) self.assertCountEqual(templater.list_themes(), [])
def _pick_color_noninteractive(templater: Templater, host_cfg: hostconfig.HostConfig, flag: str) -> str: '''Picks a color without prompting.''' return flag or templater.get_color() or host_cfg.default_color
def reload(): '''Redeploy dotfiles from the previously deployed configuration.''' host_cfg = hostconfig.from_file(ACTIVE_HOST_PATH) templater = Templater(MODOT_PATH, host_cfg) _check_and_deploy(host_cfg, templater, dryrun=False)
def test_get_theme_no_link_returns_none(self): '''Test getting theme with no link present.''' link_path = Path(self.link_dir.name) templater = Templater(link_path) self.assertIsNone(templater.get_theme())
def list_themes(): '''List all themes found in the themes directory.''' templater = Templater(MODOT_PATH, hostconfig.from_file(ACTIVE_HOST_PATH)) for name in templater.list_themes(): print(name)