如何令长字符串的yaml输出可读性更好

Python017

如何令长字符串的yaml输出可读性更好,第1张

title: THE PROBLEMS OF PHILOSOPHY

author: Bertrand Russell

这种双引号前后一闭合,管你多长的字符通通放一行,中间还可能插入各种恶心转义字符例如\\n

,可读性真的很差。python/node.js/ruby/java的yaml库都翻了遍,python比较接近*1

。各种库对输入的parse/load都很强大,但是反过来输出yaml时,就开始变成各种反人类亲机器的文件格式,完全抛弃yaml的可读性。

求推荐yaml库,可通过简单的设置或者扩展,自定义长字符串以区块的形式的输出,多于80列则自动换行,如下

title: THE PROBLEMS OF PHILOSOPHY

author: Bertrand Russellpreface:In the following pages I have confined myself in the main to those problems of

或者是扩展性比较高的格式化输出工具。

在go语言中使用viper之类的库很方便的处理yaml配置文件,但是在c语言中就比较麻烦,经过一番思索和借助强大的github,发现了一个libyaml c库,但是网上的例子都比较麻烦,而且比较繁琐,就想法作了一个相对比较容易配置的解析应用,可以简单地类似viper 的模式进行配置实现不同的配置文件读取。如你的配置文件很复杂请按格式修改KeyValue 全局变量,欢迎大家一起完善

库请自行下载 GitHub - yaml/libyaml: Canonical source repository for LibYAML

直接上代码

yaml示例文件

%YAML 1.1

---

mqtt:

subtopic: "Control/#"

pubtopic: "bbt"

qos: 1

serveraddress: "tcp://192.168.0.25:1883"

clientid: "kvm_test"

writelog: false

writetodisk: false

outputfile: "./receivedMessages.txt"

hearttime: 30

#ifndef __CONFIG_H__

#define __CONFIG_H__

#ifdef __cplusplus

extern "C" {

#endif

/************************/

/* Minimum YAML version */

/************************/

#define YAML_VERSION_MAJOR 1

#define YAML_VERSION_MINOR 1

#define STRUCT_TYPE_NAME 100

#define INT_TYPE_NAME 101

#define STRING_TYPE_NAME 102

#define BOOL_TYPE_NAME 103

#define FLOAT_TYPE_NAME 104

#define MAP_TYPE_NAME 105

#define LIST_TYPE_NAME 106

typedef struct{

char *key

void *value

int valuetype

char *parent

}KeyValue,*pKeyValue

#ifdef __cplusplus

}

#endif

#endif

#include

#include

#include

#include

#include

#include

#include

#include "config.h"

typedef struct {

char *SUBTOPIC//string `yaml:"subtopic" mapstructure:"subtopic"` //"topic1"

char *PUBTOPIC//string `yaml:"pubtopic" mapstructure:"pubtopic"`

int QOS//byte `yaml:"qos" mapstructure:"qos"` //1

char *SERVERADDRESS//string `yaml:"serveraddress" mapstructure:"serveraddress"` //= "tcp://mosquitto:1883"

char *CLIENTID//string `yaml:"clientid" mapstructure:"clientid"` //= "mqtt_subscriber"

int HEARTTIME//int `yaml:"hearttime" mapstructure:"hearttime"`

// CommandLocalPath string `yam:"commanlocalpath"`

}mqttSection,*pmqttSection

typedef struct {

mqttSection Mqtt// `yaml:"mqtt" mapstructure:"mqtt"`

// KVM kvmSection `yaml:"kvm" mapstructure:"kvm"`

}ConfigT

ConfigT config

static KeyValue webrtcconfig[]={

{"mqtt",&config,STRUCT_TYPE_NAME,NULL},

{"subtopic",&(config.Mqtt.SUBTOPIC),STRING_TYPE_NAME,"mqtt"},

{"pubtopic",&(config.Mqtt.PUBTOPIC),STRING_TYPE_NAME,"mqtt"},

{"qos",&(config.Mqtt.QOS),INT_TYPE_NAME,"mqtt"},

{"serveraddress",&(config.Mqtt.SERVERADDRESS),STRING_TYPE_NAME,"mqtt"},

{"clientid",&(config.Mqtt.CLIENTID),STRING_TYPE_NAME,"mqtt"},

{"hearttime",&(config.Mqtt.HEARTTIME),INT_TYPE_NAME,"mqtt"},

{NULL,NULL,0,NULL},

}

int printConfig(ConfigT * pconfig){

if(pconfig==NULL) return -1

printf("mqtt:r ")

if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("subtopic: %sr ",pconfig->Mqtt.SUBTOPIC)}

if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("pubtopic: %sr ",pconfig->Mqtt.PUBTOPIC)}

printf("qos: %dr ",config.Mqtt.QOS)

if(pconfig->Mqtt.SERVERADDRESS!=NULL) {printf("serveraddress: %sr ",pconfig->Mqtt.SERVERADDRESS)}

if(pconfig->Mqtt.CLIENTID!=NULL) {printf("clientid: %sr ",pconfig->Mqtt.CLIENTID)}

printf("hearttime: %dr ",config.Mqtt.HEARTTIME)

}

int freeConfig(ConfigT * pconfig){

if(pconfig==NULL) return -1

if(pconfig->Mqtt.SERVERADDRESS!=NULL) {free(pconfig->Mqtt.SERVERADDRESS)}

if(pconfig->Mqtt.CLIENTID!=NULL) {free(pconfig->Mqtt.CLIENTID)}

if(pconfig->Mqtt.SUBTOPIC!=NULL) {free(pconfig->Mqtt.SUBTOPIC)}

}

char currentkey[100]

void getvalue(yaml_event_t event,pKeyValue *ppconfigs){

char *value = (char *)event.data.scalar.value

pKeyValue pconfig=*ppconfigs

char *pstringname

while(pconfig->key!=NULL){

if(currentkey[0]!=0){

if(!strcmp(currentkey,pconfig->key))

{

switch(pconfig->valuetype){

case STRING_TYPE_NAME:

pstringname=strdup(value)

printf("get string value %sr ",pstringname)

*((char**)pconfig->value)=pstringname

memset(currentkey, 0, sizeof(currentkey))

break

case INT_TYPE_NAME:

*((int*)(pconfig->value))=atoi(value)

memset(currentkey, 0, sizeof(currentkey))

break

case BOOL_TYPE_NAME:

if(!strcmp(value,"true")) *((bool*)(pconfig->value))=true

else *((bool*)(pconfig->value))=false

memset(currentkey, 0, sizeof(currentkey))

break

case FLOAT_TYPE_NAME:

*((float*)(pconfig->value))=atof(value)

memset(currentkey, 0, sizeof(currentkey))

break

case STRUCT_TYPE_NAME:

case MAP_TYPE_NAME:

case LIST_TYPE_NAME:

memset(currentkey, 0, sizeof(currentkey))

strncpy(currentkey,value,strlen(value))

break

default:

break

}

break

}

//continue

}else{

if(!strcmp(value,pconfig->key)){

strncpy(currentkey,pconfig->key,strlen(pconfig->key))

break

}

}

pconfig++

}

}

int Load_YAML_Config( char *yaml_file, KeyValue *(configs[]) )

{

struct stat filecheck

yaml_parser_t parser

yaml_event_t event

bool done = 0

unsigned char type = 0

unsigned char sub_type = 0

if (stat(yaml_file, &filecheck) != false )

{

printf("[%s, line %d] Cannot open configuration file '%s'! %s", __FILE__, __LINE__, yaml_file, strerror(errno) )

return -1

}

FILE *fh = fopen(yaml_file, "r")

if (!yaml_parser_initialize(&parser))

{

printf("[%s, line %d] Failed to initialize the libyaml parser. Abort!", __FILE__, __LINE__)

return -1

}

if (fh == NULL)

{

printf("[%s, line %d] Failed to open the configuration file '%s' Abort!", __FILE__, __LINE__, yaml_file)

return -1

}

memset(currentkey, 0, sizeof(currentkey))

/* Set input file */

yaml_parser_set_input_file(&parser, fh)

while(!done)

{

if (!yaml_parser_parse(&parser, &event))

{

/* Useful YAML vars: parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1 */

printf( "[%s, line %d] libyam parse error at line %ld in '%s'", __FILE__, __LINE__, parser.problem_mark.line+1, yaml_file)

}

if ( event.type == YAML_DOCUMENT_START_EVENT )

{

//yaml file first line is version

//%YAML 1.1

//---

yaml_version_directive_t *ver = event.data.document_start.version_directive

if ( ver == NULL )

{

printf( "[%s, line %d] Invalid configuration file. Configuration must start with "%%YAML 1.1"", __FILE__, __LINE__)

}

int major = ver->major

int minor = ver->minor

if (! (major == YAML_VERSION_MAJOR &&minor == YAML_VERSION_MINOR) )

{

printf( "[%s, line %d] Configuration has a invalid YAML version. Must be 1.1 or above", __FILE__, __LINE__)

return -1

}

}

else if ( event.type == YAML_STREAM_END_EVENT )

{

done = true

}

else if ( event.type == YAML_MAPPING_END_EVENT )

{

sub_type = 0

}

else if ( event.type == YAML_SCALAR_EVENT )

{

getvalue(event,configs)

}

}

return 0

}

int main(int argc, char *argv[]){

pKeyValue pconfig=&webrtcconfig[0]

Load_YAML_Config("../../etc/kvmagent.yml",&pconfig)

printConfig(&config)

freeConfig(&config)

}

NetBeans IDE 是由 Sun 公司推出一款优秀、免费、开源的集成开发工具,我们可以通过其开发专业的 Java 桌面、Web、企业以及移动应用程序。它同时支持 C/C++ 甚至是 Ruby 语言的开发,并且可以运行在多个操作系统之上,包括 Windows, Linux, Mac OSX 和 Solaris。

最新发布的 NetBeans IDE 6.0 版本拥有诸多引人瞩目的新特性,包括完全重新打造的代码编辑器,众多语言的支持,简易高效的开发方式以及轻松快捷的安装和配置。

IDE :

人性化的下载和安装方式:NetBeans 6.0 的 Java SE 版本仅需 21 MB!

插件管理器:用它可以在不同版本之间轻松转换,而不必下载新的安装文件。

标准化的项目构成:NetBeans 6.0 的 Java 项目默认使用 Ant 1.7,同时支持 Maven。

模板支持:使用 NetBeans 6.0,我们可以自行创建任何种类的应用程序模板。

工具栏拖动:自定义工具栏可以直接拖动所需的按钮到所需的位置。

可分离的面板:所有的面板都可以从 IDE 中分离出来而独立使用,通过它可以实现同时编辑多个代码文件。

项目组:将多个相关联的项目定义为一个项目组,可以方便的同时打开和关闭多个相关联的项目。

任务列表:通过注释中的 TODO 或 FIXME 建立任务列表,支持导入和导出为标准的 iCalendar 格式或直接与 bug 数据库同步。

编辑器:

语言感应编辑器:支持 Java, Ruby, C/C++, XML, HTML, RHTML, JavaScript 和 JSP 语法高亮、代码缩进、关键字匹配和自动格式化,并可扩展支持其他语言。

实时语法分析:能够即时的报告错误或提示自动修复。

重构:使用 Ctrl + R 快捷键可以直接更改变量名称,省去了查找和替换的繁琐。

自动代码补全:支持 Java, Ruby, XML, C/C++, HTML, RHTML, JSP 和 JavaScript 的自动代码补全。

自动代码生成:例如,如果使用了一个未定义的方法,IDE 会提示自动创建这个方法。

本地文件历史记录:就算没有版本控制也可以轻松恢复到本地的历史版本。

快速导航:支持快速查询某个成员或错误并定位。

完全可定制的用户界面:快捷键、工具栏按钮、界面字体均可以轻松定制。

版本控制和协同开发:

集成版本控制工具:支持快速更新、签出、对比、重命名文件和提交修改。

CVS, Subversion, Mercurial:内置 CVS 和 Subversion 支持。Mercurial 的支持可以在插件管理器中安装。

文件状态和历史记录:列出当前文件状态和所有的历史版本,可以直接比较。

基于代码行的对比查看。

远程项目共享:在网络上实时共享项目,支持远程编辑代码、调试和运行。协同开发可以在插件管理器中安装。

协同开发聊天:支持即时消息通讯。

Java SE:

JDK 多版本支持:JDK 1.1 - 1.4, 5.0 和 6

桌面应用程序开发:向导式生成桌面应用程序的基本框架。

单元测试:集成 JUnit 3 和 4。

基于 Ant 的项目构成。

可视化图形界面设计:拖拽组件式 Swing 界面开发,自动生成界面代码。

调试和性能分析。

Swing 图形用户界面设计器:

专业的 GUI 编辑器:拖拽式界面设计方式,自动对齐校正,支持提示和快捷键设置。

标准和自定义 GUI 组件:除了标准的 AWT 和 Swing 组件外,可以添加扩展自定义的组件。

支持Beans 绑定技术 (JSR 295):利用 Beans 绑定技术和 JPA 的特性可以轻松快捷的创建 Swing 桌面数据库应用程序。

支持 Swing 应用程序框架 (JSR 296)。

性能分析器:

基于任务的性能分析:自定义性能分析任务,检测 CPU、内存或其他监视参数,并可以保存结果快照。

堆走查:分析堆内容,标识不必要的引用,节约内存开销。

性能分析点:可以在代码中设置性能分析点。

标识 CPU 瓶颈:可以对特定的方法做 CPU 使用时间测试。

追踪内存使用状况。

监视线程状态。

远程性能分析。

附属性能分析:就算没有使用 IDE 运行的程序,只要用的是同一个 JDK 6,也可以做性能分析。

调试器:

表达式分析和步进:鼠标点击变量可以直接查看值。

可配置的断点。

多会话和多线程调试。

堆走查。

Java EE:

支持 Java Persistence API (JSR-220), servlets, JavaServer Pages (JSP), Enterprise JavaBeans (EJB) 和 web services 开发。

完整支持 J2EE 1.3, J2EE 1.4 和 Java EE 5 标准。

Web 和应用服务器:内置 Tomcat 6 和 GlassFish v2。支持Sun Java System Application Server 8 and 9, GlassFish v1 and v2, Apache Tomcat 4, 5 and 6, JBoss 4, BEA WebLogic 10, IBM WebSphere 6 等。

代码自动完成、模板和向导:提供蓝图、模板和向导帮助我们创建 Enterprise Java Beans (EJB 3.0), servlets, JSP pages 和 JAX-WS web services 应用。

提供 Java EE 5 资源注入元注释代码自动完成功能。

Java 持久层:支持数据库拖拽自动创建实体类,并提供模板和图形化编辑器创建和维护持久层单元。

Web 应用程序:

Visual Web JSF 开发:利用 JSF 框架进行可视化 Web 设计。

HTTP 监视器:有助于组件和 Web 应用程序的跟踪和调试。

Woodstock JSF 组件:拖拽式开发 AJAX。

标准 JSF 组件:除了提供标准的 JSF 实现组件外,还包含表格、日历、树状结构、文件上传等其他复杂组件。

JSP 开发:支持 JavaServer Pages Standard Tag Library (JSTL),Struts 1.2.9 and 1.3.x,并可以通过安装插件方式支持 Wicket 和 Spring 框架。

JavaScript 编辑器:自动识别 HTML 和 JSP 页面中的 JS 代码,并提供语法高亮、代码完成和错误检查支持。

CSS 编辑器:提供 CSS 语法高亮、代码完成、错误检查支持和代码导航。Visual CSS 编辑器提供预览功能。

数据库和数据绑定工具:自定义查询、连接、结果预览。通过数据库浏览器连接数据库,直接查看视图或数据、运行 SQL 语句。支持拖拽式数据绑定。

数 据库:内置 JavaDB (Derby), MySQL and PostgreSQL 支持,并可扩展到 Oracle, IBM DB2, Microsoft SQL Server, PointBase, Sybase, Informix, Cloudscape, InstantDB, Interbase, Firebird, FirstSQL, Mckoi SQL, HSQLDB, Hypersonic SQL 和 Micrososft Access。

Web Services:

标准化 Web 开发:支持 J2EE 1.4 and Java EE 5, including the JAX-WS 2.1, JAX-RS (JSR-311), JAX-RPC (JSR-101) web service 标准。可运行在 Sun Java System Application Server (GlassFish), Apache Tomcat, IBM WebSphere, BEA Weblogic and JBoss。

可靠、安全和可转换的 Web Services:使用在 Sun Application Server (GlassFish) 提供的 Metro 支持,构建交互的、可靠的、安全的、可转换的 Web Services。使用 Sun Java System Access Manager 构建安全的,基于身份验证的 Web Services。

同步和异步 JAX-WS 支持:NetBeans 提供可视化 JAX-WS 编辑器。

基于 SOAP 和 RESTful 的 Web Services:拖拽式 RESTful 组件自动生成所需代码,例如 Google Map, Yahoo News Search 和 StrikeIron web services。

移动 Web Service:应用 JSR-172 移动应用程序。通过无线连接桥,让 MIDlets 访问 Web Service 和其他服务器端数据。

移动开发:

手机、手持设备和机顶盒:创建、测试和调试移动信息设备简表 (MIDP) 1.0, 2.0,连接受限设备配置 (CLDC) 1.0 and 1.1 和 连接设备配置 (CDC) 应用程序。

可视化移动设计工具:利用可视化移动设计工具 v2,可以更快速的拖拽式开发图形界面,例如等待界面、登陆界面、文件浏览器、短信程序和闪屏等。同时,国际化工作也会更加方便。

移动游戏构建工具 (Mobile Game Builder):使用 MIDP 2.0 游戏 API 进行可视化开发。

模块构建系统:可以为不同平台类型、部署类型和配置加入自定义的组件。

支持 Web Services 访问。

支持 SVG:更方便的创建和编辑 SVG 图形文件 (JSR-226)。

集 成工具:JMUnit testing, MIDlet signing, 认证管理, automatic code obfuscation, integrated over-the-air (OTA) emulation, push registry emulation, WMA emulation for SMS and CBS messages, new deployment methods, and Wireless Messaging and Multimedia APIs.

Ruby:

Ruby 项目:支持Ruby 文件,RSpec 标准定义文件和 YAML 文件。实时代码解析。

Ruby on Rails 项目:支持 Rake 和数据库移植。通过图形向导生成代码。

Ruby and Rails 调试器。

Ruby Gems 安装管理器。

C/C++:

C/C++ 项目和模板。

源代码编辑器:代码自动高亮、自动完成、自动格式化、匹配、折叠。

调试器:完美集成 GNU gdb 调试器。

编译器配置。

Makefile 支持。

类继承关系浏览器。

文件导航。

UML:

正向和反向工程:支持 UML 模型图生成 Java 代码。

支 持8种 UML 图:Activity diagram, Class diagram, Collaboration diagram, Component diagram, Deployment diagram, Sequence diagram, State diagram 和 Use Case diagram

自定义代码生成模式。

集成 UML 工具:支持 Telelogic DOORS 导入,支持导出 Javadoc 样式报告。

EJB 1.1, EJB 2.0 和 Gang of Four 设计模式。

SOA:

Web Services:支持文件、HTTP 和 JMS 绑定组件。

可视化 BPEL 设计工具。

可视化 XSLT 设计工具。

XML 视图向导和可视化 WSDL 编辑器。

平台:

一般桌面应用程序:提供众多基础组件,例如:窗口管理、菜单、设置、存储、更新向导和文件访问等。

富客户端开发。

模块化:动态模块装载。

一致性:一次编写、到处运行,轻松实现跨平台应用。

新的 API:Visual Library API, NetBeans Preferences API, Lexer API。