Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: CLI front-end 5 : * Author: Even Rouault <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "gdalalgorithm.h" 14 : #include "commonutils.h" 15 : 16 : #include "gdal.h" 17 : 18 : #include <cassert> 19 : 20 : // #define DEBUG_COMPLETION 21 : 22 : /************************************************************************/ 23 : /* EmitCompletion() */ 24 : /************************************************************************/ 25 : 26 : /** Return on stdout a space-separated list of choices for bash completion */ 27 68 : static void EmitCompletion(std::unique_ptr<GDALAlgorithm> rootAlg, 28 : const std::vector<std::string> &argsIn) 29 : { 30 : #ifdef DEBUG_COMPLETION 31 : for (size_t i = 0; i < argsIn.size(); ++i) 32 : fprintf(stderr, "arg[%d]='%s'\n", static_cast<int>(i), 33 : argsIn[i].c_str()); 34 : #endif 35 : 36 68 : std::vector<std::string> args = argsIn; 37 : 38 68 : std::string ret; 39 32320 : const auto addSpace = [&ret]() 40 : { 41 16192 : if (!ret.empty()) 42 16128 : ret += " "; 43 16260 : }; 44 : 45 201 : if (!args.empty() && 46 67 : (args.back() == "--config" || 47 130 : STARTS_WITH(args.back().c_str(), "--config=") || 48 126 : (args.size() >= 2 && args[args.size() - 2] == "--config"))) 49 : { 50 4 : if (args.back() == "--config=" || args.back().back() != '=') 51 : { 52 4 : CPLStringList aosConfigOptions(CPLGetKnownConfigOptions()); 53 2098 : for (const char *pszOpt : cpl::Iterate(aosConfigOptions)) 54 : { 55 2096 : addSpace(); 56 2096 : ret += pszOpt; 57 2096 : ret += '='; 58 : } 59 2 : printf("%s", ret.c_str()); 60 : } 61 4 : return; 62 : } 63 : 64 14096 : for (const auto &choice : 65 14160 : rootAlg->GetAutoComplete(args, /*showAllOptions = */ true)) 66 : { 67 14096 : addSpace(); 68 14096 : ret += CPLString(choice).replaceAll(" ", "\\ "); 69 : } 70 : 71 : #ifdef DEBUG_COMPLETION 72 : fprintf(stderr, "ret = '%s'\n", ret.c_str()); 73 : #endif 74 64 : if (!ret.empty()) 75 62 : printf("%s", ret.c_str()); 76 : } 77 : 78 : /************************************************************************/ 79 : /* main() */ 80 : /************************************************************************/ 81 : 82 92 : MAIN_START(argc, argv) 83 : { 84 92 : auto alg = GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate( 85 276 : GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME); 86 92 : assert(alg); 87 : 88 92 : if (argc >= 3 && strcmp(argv[1], "completion") == 0) 89 : { 90 68 : GDALAllRegister(); 91 : 92 : // Process lines like "gdal completion gdal raster" 93 68 : EmitCompletion(std::move(alg), 94 136 : std::vector<std::string>(argv + 3, argv + argc)); 95 68 : return 0; 96 : } 97 : 98 24 : EarlySetConfigOptions(argc, argv); 99 : 100 : /* -------------------------------------------------------------------- */ 101 : /* Register standard GDAL drivers, and process generic GDAL */ 102 : /* command options. */ 103 : /* -------------------------------------------------------------------- */ 104 : 105 24 : GDALAllRegister(); 106 : 107 24 : argc = GDALGeneralCmdLineProcessor( 108 : argc, &argv, GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER); 109 24 : if (argc < 1) 110 1 : return (-argc); 111 : 112 46 : std::vector<std::string> args; 113 116 : for (int i = 1; i < argc; ++i) 114 93 : args.push_back(argv[i]); 115 23 : CSLDestroy(argv); 116 : 117 23 : if (!alg->ParseCommandLineArguments(args)) 118 : { 119 5 : fprintf(stderr, "%s", alg->GetUsageForCLI(true).c_str()); 120 5 : return 1; 121 : } 122 : 123 : { 124 18 : const auto stdoutArg = alg->GetActualAlgorithm().GetArg("stdout"); 125 18 : if (stdoutArg && stdoutArg->GetType() == GAAT_BOOLEAN) 126 3 : stdoutArg->Set(true); 127 : } 128 : 129 : GDALProgressFunc pfnProgress = 130 18 : alg->IsProgressBarRequested() ? GDALTermProgress : nullptr; 131 18 : void *pProgressData = nullptr; 132 : 133 18 : int ret = 0; 134 18 : if (alg->Run(pfnProgress, pProgressData) && alg->Finalize()) 135 : { 136 : const auto outputArg = 137 17 : alg->GetActualAlgorithm().GetArg("output-string"); 138 20 : if (outputArg && outputArg->GetType() == GAAT_STRING && 139 3 : outputArg->IsOutput()) 140 : { 141 3 : printf("%s", outputArg->Get<std::string>().c_str()); 142 : } 143 : } 144 : else 145 : { 146 1 : ret = 1; 147 : } 148 : 149 18 : return ret; 150 : } 151 : 152 0 : MAIN_END