How to extract raw IQ data from Gnuradio meta file sink? - gnuradio

System:debian 11,Gnuradio 3.8.10,python 3.8.10
I try to use meta file sink block to record the raw IQ data with meta data.
grc file as below:
options:
parameters:
author: ''
category: '[GRC Hier Blocks]'
cmake_opt: ''
comment: ''
copyright: ''
description: ''
gen_cmake: 'On'
gen_linking: dynamic
generate_options: qt_gui
hier_block_src_path: '.:'
id: meta_sink
max_nouts: '0'
output_language: python
placement: (0,0)
qt_qss_theme: ''
realtime_scheduling: ''
run: 'True'
run_command: '{python} -u {filename}'
run_options: prompt
sizing_mode: fixed
thread_safe_setters: ''
title: Not titled yet
window_size: ''
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [8, 8]
rotation: 0
state: enabled
blocks:
- name: samp_rate
id: variable_qtgui_range
parameters:
comment: ''
gui_hint: ''
label: ''
min_len: '200'
orient: Qt.Horizontal
rangeType: float
start: '0'
step: '1'
stop: 128e3
value: 32e3
widget: counter_slider
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [384, 60.0]
rotation: 0
state: true
- name: strobe_value
id: variable_qtgui_chooser
parameters:
comment: ''
gui_hint: ''
label: ''
label0: str=0
label1: str=1
label2: ''
label3: ''
label4: ''
labels: '[]'
num_opts: '2'
option0: '0'
option1: '1'
option2: '2'
option3: '3'
option4: '4'
options: '[0, 1, 2]'
orient: Qt.QVBoxLayout
type: int
value: '0'
widget: combo_box
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [616, 20.0]
rotation: 0
state: true
- name: analog_sig_source_x_0
id: analog_sig_source_x
parameters:
affinity: ''
alias: ''
amp: '1'
comment: ''
freq: '100'
maxoutbuf: '0'
minoutbuf: '0'
offset: '0'
phase: '0'
samp_rate: samp_rate
type: complex
waveform: analog.GR_SAW_WAVE
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [80, 140.0]
rotation: 0
state: enabled
- name: blocks_file_meta_sink_0
id: blocks_file_meta_sink
parameters:
affinity: ''
alias: ''
comment: ''
detached: 'False'
extra_dict: pmt.make_dict()
file: /home/laozi/meta.bin
max_seg_size: '1000000'
rel_rate: '1'
samp_rate: samp_rate
type: complex
unbuffered: 'False'
vlen: '1'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [632, 220.0]
rotation: 0
state: enabled
- name: blocks_throttle_0
id: blocks_throttle
parameters:
affinity: ''
alias: ''
comment: ''
ignoretag: 'True'
maxoutbuf: '0'
minoutbuf: '0'
samples_per_second: samp_rate
type: complex
vlen: '1'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [448, 244.0]
rotation: 0
state: enabled
- name: import_0
id: import
parameters:
alias: ''
comment: ''
imports: import pmt
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1224, 320.0]
rotation: 0
state: true
connections:
- [analog_sig_source_x_0, '0', blocks_throttle_0, '0']
- [blocks_throttle_0, '0', blocks_file_meta_sink_0, '0']
metadata:
file_format: 1
Then,use python script to extract the raw IQ data for further process:
from gnuradio import gr,blocks
import pmt
import sys
from gnuradio.blocks import parse_file_metadata
import numpy as np
filename ='./meta.bin'
max_data_segments_to_read = 3
print_output = True
fh = open(filename, "rb")
for ii in range(max_data_segments_to_read):
header_str = fh.read(parse_file_metadata.HEADER_LENGTH)
header = pmt.deserialize_str(header_str)
print(f"\n===Data segment {ii} ===")
header_info = parse_file_metadata.parse_header(header, print_output)
if(header_info["extra_len"] > 0):
extra_str = fh.read(header_info["extra_len"])
if(len(extra_str) != 0):
extra = pmt.deserialize_str(extra_str)
extra_info = parse_file_metadata.parse_extra_dict(extra, header_info, print_output)
data=np.fromfile(file=fh, dtype=np.float32, count=int(header_info['nitems']), sep='', offset=0)
print(f"{len(data)} data elements read")
fh.close()
But I got failed as below:
===Data segment 0 ===
Version Number: 0
Sample Rate: 32000.00 sps
Seconds: 0.000000
Item size: 8
Data Type: float (5)
Complex? True
Header Length: 150 bytes
Extra Length: 1
Extra Header? True
Size of Data: 8000000 bytes
1000000.0 items
1000000 data elements read
Traceback (most recent call last):
File "/home/laozi/a.py", line 13, in <module>
header = pmt.deserialize_str(header_str)
File "/usr/lib/python3/dist-packages/pmt/pmt_swig.py", line 2898, in deserialize_str
return _deserialize_str_u8(tuple(x for x in pmt_str))
File "/usr/lib/python3/dist-packages/pmt/pmt_swig.py", line 2871, in _deserialize_str_u8
return _pmt_swig._deserialize_str_u8(py_str)
RuntimeError: pmt::deserialize: malformed input stream, tag value = : 91
Where is the problem?

Item size: 8
Size of Data: 8000000 bytes
1000000.0 items
One possible explanation is that you are not reading all the data. The metadata indicates that the size of one item is 8 bytes (two float32 numbers - one for I and one for Q) and there are 1000000 items (8000000 bytes).
data=np.fromfile(file=fh, dtype=np.float32, count=int(header_info['nitems']), sep='', offset=0)
You've specified dtype to be np.float32 (that is 4 bytes) and count is the number of items (1000000) so only 4000000 bytes are being read.
Try reading twice as much - count=2*int(header_info['nitems'])

Related

Pandas boolean condition from nested list of dictionaries

[{'id': 123,
'type': 'salary', #Parent node
'tx': 'house',
'sector': 'EU',
'transition': [{'id': 'hash', #Child node
'id': 123,
'type': 'salary',
'tx': 'house' }]},
{'userid': 123,
'type': 'salary', #Parent node
'tx': 'office',
'transition': [{'id': 'hash', # Child node
'id': 123,
'type': 'salary',
'tx': 'office'}]}]
As a pandas column ('info') I have some information stored as a nested list of dictionaries like the example above.
What I'm trying to do is a boolean condition whether this list has the following attributes:
More than one 'type' == 'salary' in any of all parents nodes
Field 'tx' is different in any of all parents nodes with 'type' == 'salary'
So far I've tried to flatten a list and filter but it is not solving the first and seconds nodes
a = df.iloc[0].info
values = [item for sublist in [[list(i.values()) for i in a]][0]for item in sublist]
If you want to one line solution, you can use:
df['check'] = df['info'].apply(lambda x: True if sum([1 if i['type']=='salary' else 0 for i in x]) > 1 and [i['tx'] for i in x if i['type']=='salary'].count([i['tx'] for i in x if i['type']=='salary'][0]) != len([i['tx'] for i in x if i['type']=='salary']) else False)
or (expanded):
def check(x):
total_salary = sum([1 if i['type']=='salary' else 0 for i in x]) # get count of "type": "salary" matches
tx_list = [i['tx'] for i in x if i['type']=='salary'] # get tx values when type==salary
tx_check = tx_list.count(tx_list[0]) != len(tx_list) # check all values are same in tx_list
if total_salary > 1 and tx_check:
return True
else:
return False
df['check'] = df['info'].apply(check)

Pubsub to BQ load using beam

I am trying to create beam code which will just load the data from pubsub to bq, when i am running the same code from colab its working perfectly but when i am creating template or dataflow as running i am getting issues not define etc.
Error = Invalid JSON payload received. Unknown name "json" at 'rows[0]': Proto field is not repeating, cannot start list. [while running 'Write Raw Data to BQ/_StreamToBigQuery/StreamInsertRows/ParDo(BigQueryWriteFn)-ptransform-60']
line 179, in process UnboundLocalError: local variable 'job' referenced before assignment [while running 'Write Raw Data to Big Query-ptransform-63'] passed through: ==> dist_proc/dax/workflow/worker/fnapi_service_impl.cc:922
Code :
import argparse
import json
import os
import logging
import pandas as pd
import apache_beam as beam
from google.cloud import bigquery, pubsub_v1
from google.cloud.bigquery import table
import google.cloud.storage.client as gcs
from apache_beam.options.pipeline_options import PipelineOptions, StandardOptions, GoogleCloudOptions, SetupOptions
import apache_beam.transforms.window as window
serviceAccount = '/content/test-project-0c3a740e58c8.json'
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]= serviceAccount
logging.basicConfig(level=logging.INFO)
logging.getLogger().setLevel(logging.INFO)
project_id = "test-project"
bigquery_dataset = "bq_load"
bigquery_message_table = "message_table"
bigquery_error_table = "Error_Table"
bigquery_message_agg_table = "message_table_aggri"
subscription_id = "topic_message-sub"
INPUT_SUBSCRIPTION = pubsub_v1.SubscriberClient().subscription_path(project_id, subscription_id)
WINDOW_SIZE = 100
client = bigquery.Client(project = project_id)
bq_dataset = client.dataset(bigquery_dataset)
bq_msg_table = bq_dataset.table(bigquery_message_table)
bq_err_table = bq_dataset.table(bigquery_error_table)
bq_agg_table = bq_dataset.table(bigquery_message_agg_table)
message_table_schema = {
'name': 'MessageType',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'Location',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'Building',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'DateTime',
'type': 'DATETIME',
'mode': 'NULLABLE'
}, {
'name': 'ID',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'TID',
'type': 'STRING',
'mode': 'NULLABLE'
}
error_table_schema = {
'name': 'Message',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'Error',
'type': 'STRING',
'mode': 'NULLABLE'
}
table_schema_agri = {
'name': 'MessageType',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'Location',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'Building',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'ID',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'TID',
'type': 'STRING',
'mode': 'NULLABLE'
}, {
'name': 'no_of_rows',
'type': 'NUMERIC',
'mode': 'NULLABLE'
}
def format_schema(schema):
formatted_schema = []
column_list = []
for row in schema:
formatted_schema.append(bigquery.SchemaField(row['name'], row['type'], row['mode']))
column_list.append(row['name'])
return formatted_schema, set(column_list)
message_job_config = bigquery.LoadJobConfig()
message_job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
message_job_config.schema, message_column_list = format_schema(message_table_schema)
print(message_column_list)
error_job_config = bigquery.LoadJobConfig()
error_job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
error_job_config.schema, error_column_list = format_schema(error_table_schema)
print(error_column_list)
agg_job_config = bigquery.LoadJobConfig()
agg_job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
agg_job_config.schema, agg_column_list = format_schema(table_schema_agri)
print(agg_column_list)
class ProcessMessage(beam.DoFn):
def process(self, message):
json_object = []
try:
message_str = message.decode("utf-8")
json_message = eval(message_str)
if isinstance(json_message, dict) and set(message_column_list).issubset(json_message.keys()):
print('{}'.format(("Formatted message", json_message)))
yield tuple(["Formatted message", json_message])
else:
print('{}'.format(("Error_Message", {"Original_Message": json_message, "Error": 'Unable to map input to table schema'})))
yield tuple(["Error_Message", {"Original_Message": json_message, "Error": 'Unable to map input to table schema'}])
except Exception as e:
print('{}'.format(("Error_Message", {"Original_Message": message_str if message_str else message, "Error": str(e)})))
yield tuple(["Error_Message", {"Original_Message": message_str if message_str else message, "Error": str(e)}])
class WriteDataframeToBQ(beam.DoFn):
def process(self, message):
global project_id
global bigquery_dataset
global bigquery_message_table
global bigquery_error_table
global bigquery_message_agg_table
global subscription_id
global client
global bq_dataset
global bq_msg_table
global bq_err_table
global bq_agg_table
if message[0] == 'Formatted message':
try:
print('Now inserting:', message[1])
job = client.load_table_from_json(message[1], BQ_MSG_TABLE, job_config = message_job_config)
job.result() # Waits for the job to complete.
print('Total {} messages successfully written to BigQuery Messsage Table'.format(len(message[1])))
# Creating aggregation dataframe
df = pd.DataFrame(message[1])
count_df= df.groupby(['MessageType','Location','Building','ID','TID']).size().reset_index(name='no_of_rows')
job = client.load_table_from_json(count_df.to_dict('records'), BQ_AGG_TABLE, job_config = agg_job_config)
job.result() # Waits for the job to complete.
print('Total {} messages successfully written to BigQuery Agree Messsage Table'.format(str(count_df.shape[0])))
except Exception as e:
# print(job.errors)
raise e
else:
try:
error_rows = [{"Message": json.dumps(m["Original_Message"]) if isinstance(m["Original_Message"], dict) else str(m["Original_Message"]), "Error": m["Error"]} for m in message[1]]
print('Now inserting:', error_rows)
job = client.load_table_from_json(error_rows, BQ_ERR_TABLE, job_config = error_job_config)
job.result() # Waits for the job to complete.
print('Total {} messages successfully written to BigQuery Error Table'.format(len(error_rows)))
except Exception as e:
#print(job.errors)
raise e
def run():
pipeline_options = {
'project': 'test-project',
'runner': 'DataflowRunner',
'region': 'us-east1',
'staging_location': 'gs://bucket12345/tmp/',
'temp_location': 'gs://bucket12345/tmp/',
'template_location': 'gs://bucket12345/template/dataflow_test_template',
'streaming': True
}
pipeline_options = PipelineOptions.from_dictionary(pipeline_options)
table = 'test-project:bq_load.message_table'
with beam.Pipeline(options=pipeline_options) as p:
( p
| "ReadFromPubSub" >> beam.io.gcp.pubsub.ReadFromPubSub(
subscription=INPUT_SUBSCRIPTION, timestamp_attribute=None
)
| "Process Message" >> beam.ParDo(ProcessMessage())
| 'Fixed-size windows' >> beam.WindowInto(window.FixedWindows(WINDOW_SIZE))
| beam.GroupByKey()
| "Write Raw Data to Big Query" >> beam.ParDo(WriteDataframeToBQ())
| "Write Raw Data to BQ" >> beam.io.WriteToBigQuery(
table,custom_gcs_temp_location = 'gs://bucket12345/template/dataflow_test_template')
)
run()

How to ignore terms in replace if they do not exist in the pandas dataframe?

I have the following code to replace one term with another, this only works if the value exists in the pandas dataframe, I assume I need to wrap gdf[montype] = gdf[montype].replace(dict(montype), regex=True) in an if statement? How would I do this, or is there a better way?
montype = [
['HIS_COP_', ''],
['_Ply', ''],
['_Pt',''],
['BURIAL','burial'],
['CUT', 'CUT'],
['MODERN', 'MODERN'],
['NATURAL', 'NATURAL'],
['STRUCTURE', 'STRUCTURE'],
['SURFACE', 'SURFACE'],
['TREETHROW', 'natural feature'],
['FURROW', 'FURROW'],
['FIELD_DRAIN', 'FIELD_DRAIN'],
['DEPOSIT_FILL', 'DEPOSIT_FILL'],
['POSTHOLE', ''],
['TIMBER', ''],
['', '']
]
gdf[montype] = gdf[montype].replace(dict(montype), regex=True)
When the term does not exist I get the error raise KeyError(f"None of [{key}] are in the [{axis_name}]")
Edit:
mtype = {
'HIS_COP_': '',
'_Ply': '',
'_Pt': '',
'BURIAL': 'burial',
'CUT': 'CUT',
'MODERN': 'MODERN',
'NATURAL': 'NATURAL',
'STRUCTURE': 'STRUCTURE',
'SURFACE': 'SURFACE',
'TREETHROW': 'natural feature',
'FURROW': 'FURROW',
'FIELD_DRAIN': 'FIELD_DRAIN',
'DEPOSIT_FILL': 'DEPOSIT_FILL',
'POSTHOLE': '',
'TIMBER': ''
} # dict(montype)
gdf['montype'] = gdf['montype'].map(mtype).fillna(gdf['montype'])
You can try this:
# Convert you list to dict
Montype={'His_cop':'','Modern':'Modern', etc...} # dict(montype)
gdf[montype]=gdf[montype].map(Montype).fillna('whatever value you want')

Exporting Tokenized SpaCy result into Excel or SQL tables

I'm using SpaCy with Pandas to get a sentence tokenised with Part of Speech (POS)export to excel. The code is as follow:
import spacy
import xlsxwriter
import pandas as pd
nlp = spacy.load('en_core_web_sm')
text ="""He is a good boy."""
doc = nlp(text)
for token in doc:
x=[token.text, token.lemma_, token.pos_, token.tag_,token.dep_,token.shape_, token.is_alpha, token.is_stop]
print(x)
When I print(x)I get the following:
['He', '-PRON-', 'PRON', 'PRP', 'nsubj', 'Xx', True, False]
['is', 'be', 'VERB', 'VBZ', 'ROOT', 'xx', True, True]
['a', 'a', 'DET', 'DT', 'det', 'x', True, True]
['good', 'good', 'ADJ', 'JJ', 'amod', 'xxxx', True, False]
['boy', 'boy', 'NOUN', 'NN', 'attr', 'xxx', True, False]
['.', '.', 'PUNCT', '.', 'punct', '.', False, False]
To the token loop, I added the DataFrame as follow:
for token in doc:
for token in doc:
x=[token.text, token.lemma_, token.pos_, token.tag_,token.dep_,token.shape_, token.is_alpha, token.is_stop]
df=pd.Dataframe(x)
print(df)
Now, I stat to get the following format:
0
0 He
1 -PRON-
2 PRON
3 PRP
4 nsubj
5 Xx
6 True
7 False
........
........
However, when I try exporting the output (df) to excel using Pandas as the following code, it only shows me the last iteration of x in the column
df=pd.DataFrame(x)
writer = pd.ExcelWriter('pandas_simple.xlsx', engine='xlsxwriter')
df.to_excel(writer,sheet_name='Sheet1')
Output (in Excel Sheet):
0
0 .
1 .
2 PUNCT
3 .
4 punct
5 .
6 False
7 False
How I can have all the iterations one after the other in the new column in this scenario as follow?
0 He is ….
1 -PRON- be ….
2 PRON VERB ….
3 PRP VBZ ….
4 nsubj ROOT ….
5 Xx xx ….
6 True True ….
7 False True ….
Some shorter code:
import spacy
import pandas as pd
nlp = spacy.load('en_core_web_sm')
text ="""He is a good boy."""
param = [[token.text, token.lemma_, token.pos_,
token.tag_,token.dep_,token.shape_,
token.is_alpha, token.is_stop] for token in nlp(text)]
df=pd.DataFrame(param)
headers = ['text', 'lemma', 'pos', 'tag', 'dep',
'shape', 'is_alpha', 'is_stop']
df.columns = headers
In case you don't have your version yet:
import pandas as pd
rows =[
['He', '-PRON-', 'PRON', 'PRP', 'nsubj', 'Xx', True, False],
['is', 'be', 'VERB', 'VBZ', 'ROOT', 'xx', True, True],
['a', 'a', 'DET', 'DT', 'det', 'x', True, True],
['good', 'good', 'ADJ', 'JJ', 'amod', 'xxxx', True, False],
['boy', 'boy', 'NOUN', 'NN', 'attr', 'xxx', True, False],
['.', '.', 'PUNCT', '.', 'punct', '.', False, False],
]
headers = ['text', 'lemma', 'pos', 'tag', 'dep',
'shape', 'is_alpha', 'is_stop']
# example 1: list of lists of dicts
#following https://stackoverflow.com/a/28058264/1758363
d = []
for row in rows:
dict_ = {k:v for k, v in zip(headers, row)}
d.append(dict_)
df = pd.DataFrame(d)[headers]
# example 2: appending dicts
df2 = pd.DataFrame(columns=headers)
for row in rows:
dict_ = {k:v for k, v in zip(headers, row)}
df2 = df2.append(dict_, ignore_index=True)
#example 3: lists of dicts created with map() function
def as_dict(row):
return {k:v for k, v in zip(headers, row)}
df3 = pd.DataFrame(list(map(as_dict, rows)))[headers]
def is_equal(df_a, df_b):
"""Substitute for pd.DataFrame.equals()"""
return (df_a == df_b).all().all()
assert is_equal(df, df2)
assert is_equal(df2, df3)

What is the standard way to diagram a redis (key-value) data structure?

I am working on creating a redis (key-value) database, and I want to be able to easily change the diagram which represents how the data should be stored.
Included in this diagram I want to be able to distinguish data which is saved as a string of JSON, vs that which is actually a hash table, or a set or an ordered set.
I tried writing something up in excel, but it was too much like a relational database, I tried writing it in JSON but it was hard to tell what was a value of a JSON string, and which were hashes.
Is there an industry standard on how to diagram this?
EDIT:
I ended up making my own syntax, but would still like to know the answer to this.
This is the syntax I created for myself: (And here is a sample Redis structure of a card game I was going to make: http://pastebin.com/4aRye4HQ)
key: = string
#key: = hash
$key: = set
$$key: = sortedSet
This is the Sublime syntax highlighting file I used to color code the syntax (Saved as redis.YAML-tmLanguage ):
# [PackageDev] target_format: plist, ext: tmLanguage
---
name: Redis
scopeName: source.redis
fileTypes: []
uuid: 0033bdf9-cd9f-4147-bd2e-a9fed3d07e1e
patterns:
- include: '#erb'
- match: \#[A-Za-z][A-Za-z0-9_]+
name: variable.parameter
comment: Hashes
- match: \$[A-Za-z][A-Za-z0-9_]+
name: support.constant
comment: Sets
- match: \$\$[A-Za-z][A-Za-z0-9_]+
name: entity.name.class
comment: Sets
- match: \d+
name: constant.numeric
comment: Numbers
- name: constant.numeric.yaml
match: (?:(?:(-\s*)?(\w+\s*(:)))|(-))\s*((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\s*$
captures:
'1': {name: punctuation.definition.entry.yaml}
'2': {name: entity.name.tag.yaml}
'3': {name: punctuation.separator.key-value.yaml}
'4': {name: punctuation.definition.entry.yaml}
- name: string.unquoted.yaml
match: (?:(?:(-\s*)?(\w+\s*(:)))|(-))\s*(?:((")[^"]*("))|((')[^']*('))|([^,{}&#\[\]]+))\s*
captures:
'1': {name: punctuation.definition.entry.yaml}
'2': {name: entity.name.tag.yaml}
'3': {name: punctuation.separator.key-value.yaml}
'4': {name: punctuation.definition.entry.yaml}
'5': {name: string.quoted.double.yaml}
'6': {name: punctuation.definition.string.begin.yaml}
'7': {name: punctuation.definition.string.end.yaml}
'8': {name: string.quoted.single.yaml}
'9': {name: punctuation.definition.string.begin.yaml}
'10': {name: punctuation.definition.string.end.yaml}
'11': {name: string.unquoted.yaml}
- name: constant.other.date.yaml
match: (?:(?:(-\s*)?(\w+\s*(:)))|(-))\s*([0-9]{4}-[0-9]{2}-[0-9]{2})\s*$
captures:
'1': {name: punctuation.definition.entry.yaml}
'2': {name: entity.name.tag.yaml}
'3': {name: punctuation.separator.key-value.yaml}
'4': {name: punctuation.definition.entry.yaml}
- include: '#value'
repository:
array:
name: meta.structure.array.json
begin: \[
beginCaptures:
'0': {name: punctuation.definition.array.begin.json}
end: \]
endCaptures:
'0': {name: punctuation.definition.array.end.json}
patterns:
- include: '#value'
- name: punctuation.separator.array.json
match: ','
- name: invalid.illegal.expected-array-separator.json
match: '[^\s\]]'
comments:
patterns:
- name: comment.block.documentation.json
begin: /\*\*
end: \*/
captures:
'0': {name: punctuation.definition.comment.json}
- name: comment.block.json
begin: /\*
end: \*/
captures:
'0': {name: punctuation.definition.comment.json}
- name: comment.line.double-slash.js
match: (//).*$\n?
captures:
'1': {name: punctuation.definition.comment.json}
constant:
name: constant.language.json
match: \b(?:true|false|null)\b
number:
comment: handles integer and decimal numbers
name: constant.numeric.json
match: "(?x: # turn on extended mode\n\t\t\t -? #\
\ an optional minus\n\t\t\t (?:\n\t\t\t 0 #\
\ a zero\n\t\t\t | # ...or...\n\t\t\t [1-9]\
\ # a 1-9 character\n\t\t\t \\d* # followed by zero or\
\ more digits\n\t\t\t )\n\t\t\t (?:\n\t\t\t \
\ (?:\n\t\t\t \\. # a period\n\t\t\t \
\ \\d+ # followed by one or more digits\n\t\t\t )?\n\t\t\
\t (?:\n\t\t\t [eE] # an e character\n\t\t\t\
\ [+-]? # followed by an option +/-\n\t\t\t \
\ \\d+ # followed by one or more digits\n\t\t\t )? #\
\ make exponent optional\n\t\t\t )? # make decimal portion\
\ optional\n\t\t\t )"
object:
comment: a JSON object
name: meta.structure.dictionary.json
begin: \{
beginCaptures:
'0': {name: punctuation.definition.dictionary.begin.json}
end: \}
endCaptures:
'0': {name: punctuation.definition.dictionary.end.json}
patterns:
- comment: the JSON object key
include: '#string'
- include: '#comments'
- name: meta.structure.dictionary.value.json
begin: ':'
beginCaptures:
'0': {name: punctuation.separator.dictionary.key-value.json}
end: (,)|(?=\})
endCaptures:
'1': {name: punctuation.separator.dictionary.pair.json}
patterns:
- comment: the JSON object value
include: '#value'
- name: invalid.illegal.expected-dictionary-separator.json
match: '[^\s,]'
- name: invalid.illegal.expected-dictionary-separator.json
match: '[^\s\}]'
string:
name: string.quoted.double.json
begin: '"'
beginCaptures:
'0': {name: punctuation.definition.string.begin.json}
end: '"'
endCaptures:
'0': {name: punctuation.definition.string.end.json}
patterns:
- name: constant.character.escape.json
match: |-
(?x: # turn on extended mode
\\ # a literal backslash
(?: # ...followed by...
["\\/bfnrt] # one of these characters
| # ...or...
u # a u
[0-9a-fA-F]{4} # and four hex digits
)
)
- name: invalid.illegal.unrecognized-string-escape.json
match: \\.
value:
comment: "the 'value' diagram at http://json.org"
patterns:
- include: '#constant'
- include: '#number'
- include: '#string'
- include: '#array'
- include: '#object'
- include: '#comments'
foldingStartMarker: |-
(?x: # turn on extended mode
^ # a line beginning with
\s* # some optional space
[{\[] # the start of an object or array
(?! # but not followed by
.* # whatever
[}\]] # and the close of an object or array
,? # an optional comma
\s* # some optional space
$ # at the end of the line
)
| # ...or...
[{\[] # the start of an object or array
\s* # some optional space
$ # at the end of the line
)
foldingStopMarker: |-
(?x: # turn on extended mode
^ # a line beginning with
\s* # some optional space
[}\]] # and the close of an object or array
)
keyEquivalent: ^~J
...