001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2023-2026 The Enola <https://enola.dev> Authors 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package dev.enola.cli.common; 019 020import static picocli.CommandLine.ScopeType.INHERIT; 021import static picocli.CommandLine.Spec.Target.MIXEE; 022 023import dev.enola.common.Version; 024import dev.enola.common.logging.JavaUtilLogging; 025 026import picocli.CommandLine; 027import picocli.CommandLine.Model.CommandSpec; 028import picocli.CommandLine.Option; 029import picocli.CommandLine.Spec; 030 031import java.util.logging.Level; 032 033public class LoggingMixin { 034 035 // https://picocli.info/#_use_case_configure_log_level_with_a_global_option 036 037 @Spec(MIXEE) 038 CommandSpec mixee; 039 040 private static Level calcLogLevel(int level) { 041 switch (level) { 042 case 0: 043 return Level.OFF; 044 case 1: 045 return Level.SEVERE; // AKA JUL ERROR 046 case 2: 047 return Level.WARNING; 048 case 3: 049 return Level.CONFIG; // incl. JUL & SLF4j INFO 050 case 4: 051 return Level.FINE; // incl. SLF4j DEBUG 052 case 5: 053 return Level.FINER; // unchanged for SLF4j 054 case 6: 055 return Level.FINEST; // incl. SLF4j TRACE 056 } 057 return Level.ALL; 058 } 059 060 public static int executionStrategy(CommandLine.ParseResult parseResult) { 061 var app = (Application) parseResult.commandSpec().root().userObject(); 062 var level = calcLogLevel(app.loggingVerbosity); 063 064 JavaUtilLogging.configure(level); 065 app.loggingIsConfigured(); 066 app.log() 067 .error( 068 """ 069 Hi! \uD83D\uDC4B I'm https://Enola.dev {}. \ 070 \uD83D\uDC7D Resistance \uD83D\uDC7E is futile. We are ONE. \ 071 What's your goal, today? \ 072 """, 073 Version.get()); 074 075 app.start(); 076 077 // And now back to and onwards with the default execution strategy 078 return new CommandLine.RunLast().execute(parseResult); 079 } 080 081 @Option( 082 names = {"--verbose", "-v"}, 083 scope = INHERIT, 084 description = { 085 "Error verbosity; specify multiple -v options to increase it; e.g. -v -v -v or" 086 + " -vvv." 087 }) 088 public void setVerbose(boolean[] verbosity) { 089 var app = (Application) mixee.root().userObject(); 090 app.loggingVerbosity = verbosity.length; 091 } 092 093 // NB Because slf4j-jdk14-*.jar is on the classpath, 094 // we do not need to configure SLF4j, only java.util.logging; 095 // see https://www.slf4j.org/manual.html#swapping. 096}