Browse Source

refactor attribute key

appflowy 3 năm trước cách đây
mục cha
commit
4d139b3f56
83 tập tin đã thay đổi với 480 bổ sung1044 xóa
  1. 1 1
      backend/src/service/doc_service/mod.rs
  2. 1 1
      backend/src/service/workspace_service/user_default/user_default.rs
  3. 0 7
      backend/tests/api/helper.rs
  4. 0 1
      backend/tests/api/workspace.rs
  5. 0 2
      rust-lib/dart-ffi/src/protobuf/mod.rs
  6. 5 5
      rust-lib/dart-ffi/src/protobuf/model/mod.rs
  7. 4 14
      rust-lib/flowy-ast/src/ast.rs
  8. 42 118
      rust-lib/flowy-ast/src/attr.rs
  9. 1 3
      rust-lib/flowy-ast/src/ctxt.rs
  10. 1 7
      rust-lib/flowy-database/src/schema.rs
  11. 1 3
      rust-lib/flowy-derive/src/dart_event/mod.rs
  12. 2 4
      rust-lib/flowy-derive/src/derive_cache/derive_cache.rs
  13. 3 9
      rust-lib/flowy-derive/src/lib.rs
  14. 15 35
      rust-lib/flowy-derive/src/proto_buf/deserialize.rs
  15. 1 5
      rust-lib/flowy-derive/src/proto_buf/mod.rs
  16. 4 15
      rust-lib/flowy-derive/src/proto_buf/serialize.rs
  17. 1 4
      rust-lib/flowy-derive/src/proto_buf/util.rs
  18. 2 6
      rust-lib/flowy-dispatch/src/data.rs
  19. 1 9
      rust-lib/flowy-dispatch/src/lib.rs
  20. 5 17
      rust-lib/flowy-dispatch/src/module/container.rs
  21. 1 4
      rust-lib/flowy-dispatch/src/module/data.rs
  22. 1 3
      rust-lib/flowy-dispatch/src/response/responder.rs
  23. 3 9
      rust-lib/flowy-dispatch/src/service/boxed.rs
  24. 1 3
      rust-lib/flowy-dispatch/src/service/service.rs
  25. 2 8
      rust-lib/flowy-dispatch/src/system.rs
  26. 2 10
      rust-lib/flowy-dispatch/src/util/mod.rs
  27. 1 1
      rust-lib/flowy-dispatch/tests/api/helper.rs
  28. 0 2
      rust-lib/flowy-document/src/protobuf/mod.rs
  29. 9 9
      rust-lib/flowy-document/src/protobuf/model/mod.rs
  30. 2 2
      rust-lib/flowy-document/src/services/doc_controller.rs
  31. 0 2
      rust-lib/flowy-infra/src/protobuf/mod.rs
  32. 3 3
      rust-lib/flowy-infra/src/protobuf/model/mod.rs
  33. 1 1
      rust-lib/flowy-log/src/layer.rs
  34. 2 2
      rust-lib/flowy-log/src/lib.rs
  35. 1 4
      rust-lib/flowy-net/src/response/response.rs
  36. 2 2
      rust-lib/flowy-net/src/response/response_serde.rs
  37. 0 2
      rust-lib/flowy-observable/src/protobuf/mod.rs
  38. 3 3
      rust-lib/flowy-observable/src/protobuf/model/mod.rs
  39. 1 0
      rust-lib/flowy-ot/src/client/document/selection.rs
  40. 1 6
      rust-lib/flowy-ot/src/client/extensions/delete/default_delete.rs
  41. 4 7
      rust-lib/flowy-ot/src/client/extensions/delete/preserve_line_format_merge.rs
  42. 4 4
      rust-lib/flowy-ot/src/client/extensions/format/helper.rs
  43. 5 7
      rust-lib/flowy-ot/src/client/extensions/format/resolve_block_format.rs
  44. 3 3
      rust-lib/flowy-ot/src/client/extensions/insert/auto_format.rs
  45. 2 18
      rust-lib/flowy-ot/src/client/extensions/insert/mod.rs
  46. 5 13
      rust-lib/flowy-ot/src/client/extensions/insert/preserve_block_format.rs
  47. 5 5
      rust-lib/flowy-ot/src/client/extensions/insert/preserve_inline_format.rs
  48. 1 1
      rust-lib/flowy-ot/src/client/extensions/insert/reset_format_on_new_line.rs
  49. 1 6
      rust-lib/flowy-ot/src/client/history.rs
  50. 3 18
      rust-lib/flowy-ot/src/client/view.rs
  51. 98 88
      rust-lib/flowy-ot/src/core/attributes/attribute.rs
  52. 27 34
      rust-lib/flowy-ot/src/core/attributes/attributes.rs
  53. 1 3
      rust-lib/flowy-ot/src/core/attributes/attributes_serde.rs
  54. 2 44
      rust-lib/flowy-ot/src/core/attributes/builder.rs
  55. 4 8
      rust-lib/flowy-ot/src/core/delta/builder.rs
  56. 2 6
      rust-lib/flowy-ot/src/core/delta/cursor.rs
  57. 8 8
      rust-lib/flowy-ot/src/core/delta/delta.rs
  58. 1 3
      rust-lib/flowy-ot/src/core/delta/delta_serde.rs
  59. 2 6
      rust-lib/flowy-ot/src/core/delta/iterator.rs
  60. 8 27
      rust-lib/flowy-ot/src/core/interval.rs
  61. 8 31
      rust-lib/flowy-ot/src/core/operation/operation.rs
  62. 3 14
      rust-lib/flowy-ot/src/errors.rs
  63. 28 73
      rust-lib/flowy-ot/tests/attribute_test.rs
  64. 13 32
      rust-lib/flowy-ot/tests/helper/mod.rs
  65. 23 71
      rust-lib/flowy-ot/tests/op_test.rs
  66. 8 2
      rust-lib/flowy-ot/tests/serde_test.rs
  67. 8 27
      rust-lib/flowy-ot/tests/undo_redo_test.rs
  68. 2 11
      rust-lib/flowy-sqlite/src/conn_ext.rs
  69. 1 4
      rust-lib/flowy-sqlite/src/database.rs
  70. 1 7
      rust-lib/flowy-sqlite/src/errors.rs
  71. 1 3
      rust-lib/flowy-sqlite/src/pool.rs
  72. 6 25
      rust-lib/flowy-sqlite/src/pragma.rs
  73. 1 3
      rust-lib/flowy-user/src/entities/parser/user_email.rs
  74. 1 4
      rust-lib/flowy-user/src/errors.rs
  75. 0 2
      rust-lib/flowy-user/src/protobuf/mod.rs
  76. 13 13
      rust-lib/flowy-user/src/protobuf/model/mod.rs
  77. 1 5
      rust-lib/flowy-workspace/src/entities/workspace/workspace_delete.rs
  78. 9 10
      rust-lib/flowy-workspace/src/handlers/view_handler.rs
  79. 6 19
      rust-lib/flowy-workspace/src/macros.rs
  80. 0 2
      rust-lib/flowy-workspace/src/protobuf/mod.rs
  81. 33 33
      rust-lib/flowy-workspace/src/protobuf/model/mod.rs
  82. 1 1
      rust-lib/flowy-workspace/src/services/app_controller.rs
  83. 1 1
      rust-lib/flowy-workspace/tests/workspace/helper.rs

+ 1 - 1
backend/src/service/doc_service/mod.rs

@@ -2,5 +2,5 @@ mod doc;
 pub mod router;
 mod sql_builder;
 
-pub use doc::*;
+pub(crate) use doc::*;
 pub use router::*;

+ 1 - 1
backend/src/service/workspace_service/user_default/user_default.rs

@@ -4,7 +4,7 @@ use flowy_workspace::protobuf::{App, CreateViewParams, View, ViewType, Workspace
 use crate::{
     service::workspace_service::{
         app::sql_builder::NewAppSqlBuilder as AppBuilder,
-        view::{create_view_with_transaction, sql_builder::NewViewSqlBuilder as ViewBuilder},
+        view::create_view_with_transaction,
         workspace::sql_builder::NewWorkspaceBuilder as WorkspaceBuilder,
     },
     sqlx_ext::{map_sqlx_error, DBTransaction},

+ 0 - 7
backend/tests/api/helper.rs

@@ -156,13 +156,6 @@ impl TestServer {
             .unwrap();
     }
 
-    pub async fn update_doc(&self, params: UpdateDocParams) {
-        let url = format!("{}/api/doc", self.address);
-        let _ = update_doc_request(self.user_token(), params, &url)
-            .await
-            .unwrap();
-    }
-
     pub async fn read_doc(&self, params: QueryDocParams) -> Option<Doc> {
         let url = format!("{}/api/doc", self.address);
         let doc = read_doc_request(self.user_token(), params, &url)

+ 0 - 1
backend/tests/api/workspace.rs

@@ -7,7 +7,6 @@ use flowy_workspace::entities::{
         DeleteWorkspaceParams,
         QueryWorkspaceParams,
         UpdateWorkspaceParams,
-        Workspace,
     },
 };
 

+ 0 - 2
rust-lib/dart-ffi/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 5 - 5
rust-lib/dart-ffi/src/protobuf/model/mod.rs

@@ -1,7 +1,7 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod ffi_response; 
-pub use ffi_response::*; 
+mod ffi_response;
+pub use ffi_response::*;
 
-mod ffi_request; 
-pub use ffi_request::*; 
+mod ffi_request;
+pub use ffi_request::*;

+ 4 - 14
rust-lib/flowy-ast/src/ast.rs

@@ -47,9 +47,7 @@ pub enum ASTData<'a> {
 impl<'a> ASTData<'a> {
     pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a ASTField<'a>> + 'a> {
         match self {
-            ASTData::Enum(variants) => {
-                Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
-            },
+            ASTData::Enum(variants) => Box::new(variants.iter().flat_map(|variant| variant.fields.iter())),
             ASTData::Struct(_, fields) => Box::new(fields.iter()),
         }
     }
@@ -120,10 +118,7 @@ impl<'a> ASTField<'a> {
             Some(inner) => {
                 match inner.primitive_ty {
                     PrimitiveTy::Map(map_info) => {
-                        bracket_category = Some(BracketCategory::Map((
-                            map_info.key.clone(),
-                            map_info.value.clone(),
-                        )))
+                        bracket_category = Some(BracketCategory::Map((map_info.key.clone(), map_info.value.clone())))
                     },
                     PrimitiveTy::Vec => {
                         bracket_category = Some(BracketCategory::Vec);
@@ -198,9 +193,7 @@ pub enum ASTStyle {
 pub fn struct_from_ast<'a>(cx: &Ctxt, fields: &'a syn::Fields) -> (ASTStyle, Vec<ASTField<'a>>) {
     match fields {
         syn::Fields::Named(fields) => (ASTStyle::Struct, fields_from_ast(cx, &fields.named)),
-        syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
-            (ASTStyle::NewType, fields_from_ast(cx, &fields.unnamed))
-        },
+        syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (ASTStyle::NewType, fields_from_ast(cx, &fields.unnamed)),
         syn::Fields::Unnamed(fields) => (ASTStyle::Tuple, fields_from_ast(cx, &fields.unnamed)),
         syn::Fields::Unit => (ASTStyle::Unit, Vec::new()),
     }
@@ -228,10 +221,7 @@ pub fn enum_from_ast<'a>(
         .collect()
 }
 
-fn fields_from_ast<'a>(
-    cx: &Ctxt,
-    fields: &'a Punctuated<syn::Field, Token![,]>,
-) -> Vec<ASTField<'a>> {
+fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a Punctuated<syn::Field, Token![,]>) -> Vec<ASTField<'a>> {
     fields
         .iter()
         .enumerate()

+ 42 - 118
rust-lib/flowy-ast/src/attr.rs

@@ -22,12 +22,7 @@ impl AttrsContainer {
     pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
         let mut pb_struct_type = ASTAttr::none(cx, PB_STRUCT);
         let mut pb_enum_type = ASTAttr::none(cx, PB_ENUM);
-        for meta_item in item
-            .attrs
-            .iter()
-            .flat_map(|attr| get_meta_items(cx, attr))
-            .flatten()
-        {
+        for meta_item in item.attrs.iter().flat_map(|attr| get_meta_items(cx, attr)).flatten() {
             match &meta_item {
                 // Parse `#[pb(struct = "Type")]
                 Meta(NameValue(m)) if m.path == PB_STRUCT => {
@@ -44,15 +39,8 @@ impl AttrsContainer {
                 },
 
                 Meta(meta_item) => {
-                    let path = meta_item
-                        .path()
-                        .into_token_stream()
-                        .to_string()
-                        .replace(' ', "");
-                    cx.error_spanned_by(
-                        meta_item.path(),
-                        format!("unknown pb container attribute `{}`", path),
-                    );
+                    let path = meta_item.path().into_token_stream().to_string().replace(' ', "");
+                    cx.error_spanned_by(meta_item.path(), format!("unknown pb container attribute `{}`", path));
                 },
 
                 Lit(lit) => {
@@ -103,8 +91,7 @@ impl<'c, T> ASTAttr<'c, T> {
         let tokens = obj.into_token_stream();
 
         if self.value.is_some() {
-            self.cx
-                .error_spanned_by(tokens, format!("duplicate attribute `{}`", self.name));
+            self.cx.error_spanned_by(tokens, format!("duplicate attribute `{}`", self.name));
         } else {
             self.tokens = tokens;
             self.value = Some(value);
@@ -160,12 +147,7 @@ impl ASTAttrField {
             None => index.to_string(),
         };
 
-        for meta_item in field
-            .attrs
-            .iter()
-            .flat_map(|attr| get_meta_items(cx, attr))
-            .flatten()
-        {
+        for meta_item in field.attrs.iter().flat_map(|attr| get_meta_items(cx, attr)).flatten() {
             match &meta_item {
                 // Parse `#[pb(skip)]`
                 Meta(Path(word)) if word == SKIP => {
@@ -200,15 +182,8 @@ impl ASTAttrField {
                 },
 
                 Meta(meta_item) => {
-                    let path = meta_item
-                        .path()
-                        .into_token_stream()
-                        .to_string()
-                        .replace(' ', "");
-                    cx.error_spanned_by(
-                        meta_item.path(),
-                        format!("unknown field attribute `{}`", path),
-                    );
+                    let path = meta_item.path().into_token_stream().to_string().replace(' ', "");
+                    cx.error_spanned_by(meta_item.path(), format!("unknown field attribute `{}`", path));
                 },
 
                 Lit(lit) => {
@@ -273,12 +248,7 @@ pub struct ASTEnumAttrVariant {
 }
 
 impl ASTEnumAttrVariant {
-    pub fn from_ast(
-        ctxt: &Ctxt,
-        ident: &syn::Ident,
-        variant: &syn::Variant,
-        enum_attrs: &Vec<syn::Attribute>,
-    ) -> Self {
+    pub fn from_ast(ctxt: &Ctxt, ident: &syn::Ident, variant: &syn::Variant, enum_attrs: &Vec<syn::Attribute>) -> Self {
         let enum_item_name = variant.ident.to_string();
         let enum_name = ident.to_string();
         let mut value = String::new();
@@ -311,11 +281,7 @@ impl ASTEnumAttrVariant {
     pub fn event_error(&self) -> String { self.event_attrs.error_ty.as_ref().unwrap().clone() }
 }
 
-fn get_event_attrs_from(
-    ctxt: &Ctxt,
-    variant_attrs: &Vec<syn::Attribute>,
-    enum_attrs: &Vec<syn::Attribute>,
-) -> EventAttrs {
+fn get_event_attrs_from(ctxt: &Ctxt, variant_attrs: &Vec<syn::Attribute>, enum_attrs: &Vec<syn::Attribute>) -> EventAttrs {
     let mut event_attrs = EventAttrs {
         input: None,
         output: None,
@@ -325,13 +291,7 @@ fn get_event_attrs_from(
 
     enum_attrs
         .iter()
-        .filter(|attr| {
-            attr.path
-                .segments
-                .iter()
-                .find(|s| s.ident == EVENT_ERR)
-                .is_some()
-        })
+        .filter(|attr| attr.path.segments.iter().find(|s| s.ident == EVENT_ERR).is_some())
         .for_each(|attr| {
             if let Ok(NameValue(named_value)) = attr.parse_meta() {
                 if let syn::Lit::Str(s) = named_value.lit {
@@ -344,48 +304,34 @@ fn get_event_attrs_from(
             }
         });
 
-    let mut extract_event_attr =
-        |attr: &syn::Attribute, meta_item: &syn::NestedMeta| match &meta_item {
-            Meta(NameValue(name_value)) => {
-                if name_value.path == EVENT_INPUT {
-                    if let syn::Lit::Str(s) = &name_value.lit {
-                        let input_type = parse_lit_str(s)
-                            .map_err(|_| {
-                                ctxt.error_spanned_by(
-                                    s,
-                                    format!("failed to parse request deserializer {:?}", s.value()),
-                                )
-                            })
-                            .unwrap();
-                        event_attrs.input = Some(input_type);
-                    }
+    let mut extract_event_attr = |attr: &syn::Attribute, meta_item: &syn::NestedMeta| match &meta_item {
+        Meta(NameValue(name_value)) => {
+            if name_value.path == EVENT_INPUT {
+                if let syn::Lit::Str(s) = &name_value.lit {
+                    let input_type = parse_lit_str(s)
+                        .map_err(|_| ctxt.error_spanned_by(s, format!("failed to parse request deserializer {:?}", s.value())))
+                        .unwrap();
+                    event_attrs.input = Some(input_type);
                 }
+            }
 
-                if name_value.path == EVENT_OUTPUT {
-                    if let syn::Lit::Str(s) = &name_value.lit {
-                        let output_type = parse_lit_str(s)
-                            .map_err(|_| {
-                                ctxt.error_spanned_by(
-                                    s,
-                                    format!(
-                                        "failed to parse response deserializer {:?}",
-                                        s.value()
-                                    ),
-                                )
-                            })
-                            .unwrap();
-                        event_attrs.output = Some(output_type);
-                    }
+            if name_value.path == EVENT_OUTPUT {
+                if let syn::Lit::Str(s) = &name_value.lit {
+                    let output_type = parse_lit_str(s)
+                        .map_err(|_| ctxt.error_spanned_by(s, format!("failed to parse response deserializer {:?}", s.value())))
+                        .unwrap();
+                    event_attrs.output = Some(output_type);
                 }
-            },
-            Meta(Path(word)) => {
-                if word == EVENT_IGNORE && attr.path == EVENT {
-                    event_attrs.ignore = true;
-                }
-            },
-            Lit(s) => ctxt.error_spanned_by(s, "unexpected attribute"),
-            _ => ctxt.error_spanned_by(meta_item, "unexpected attribute"),
-        };
+            }
+        },
+        Meta(Path(word)) => {
+            if word == EVENT_IGNORE && attr.path == EVENT {
+                event_attrs.ignore = true;
+            }
+        },
+        Lit(s) => ctxt.error_spanned_by(s, "unexpected attribute"),
+        _ => ctxt.error_spanned_by(meta_item, "unexpected attribute"),
+    };
 
     let attr_meta_items_info = variant_attrs
         .iter()
@@ -396,9 +342,7 @@ fn get_event_attrs_from(
         .collect::<Vec<(&syn::Attribute, Vec<syn::NestedMeta>)>>();
 
     for (attr, nested_metas) in attr_meta_items_info {
-        nested_metas
-            .iter()
-            .for_each(|meta_item| extract_event_attr(attr, meta_item))
+        nested_metas.iter().for_each(|meta_item| extract_event_attr(attr, meta_item))
     }
 
     // eprintln!("😁{:#?}", event_attrs);
@@ -426,15 +370,9 @@ pub fn get_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result<Vec<syn::Neste
     }
 }
 
-fn parse_lit_into_expr_path(
-    cx: &Ctxt,
-    attr_name: Symbol,
-    lit: &syn::Lit,
-) -> Result<syn::ExprPath, ()> {
+fn parse_lit_into_expr_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::ExprPath, ()> {
     let string = get_lit_str(cx, attr_name, lit)?;
-    parse_lit_str(string).map_err(|_| {
-        cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
-    })
+    parse_lit_str(string).map_err(|_| cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())))
 }
 
 fn get_lit_str<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'a syn::LitStr, ()> {
@@ -443,10 +381,7 @@ fn get_lit_str<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'
     } else {
         cx.error_spanned_by(
             lit,
-            format!(
-                "expected pb {} attribute to be a string: `{} = \"...\"`",
-                attr_name, attr_name
-            ),
+            format!("expected pb {} attribute to be a string: `{} = \"...\"`", attr_name, attr_name),
         );
         Err(())
     }
@@ -455,12 +390,7 @@ fn get_lit_str<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'
 fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Type, ()> {
     let string = get_lit_str(cx, attr_name, lit)?;
 
-    parse_lit_str(string).map_err(|_| {
-        cx.error_spanned_by(
-            lit,
-            format!("failed to parse type: {} = {:?}", attr_name, string.value()),
-        )
-    })
+    parse_lit_str(string).map_err(|_| cx.error_spanned_by(lit, format!("failed to parse type: {} = {:?}", attr_name, string.value())))
 }
 
 pub fn parse_lit_str<T>(s: &syn::LitStr) -> parse::Result<T>
@@ -477,10 +407,7 @@ fn spanned_tokens(s: &syn::LitStr) -> parse::Result<TokenStream> {
 }
 
 fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
-    stream
-        .into_iter()
-        .map(|token| respan_token_tree(token, span))
-        .collect()
+    stream.into_iter().map(|token| respan_token_tree(token, span)).collect()
 }
 
 fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
@@ -499,10 +426,7 @@ fn default_pb_type(ctxt: &Ctxt, ident: &syn::Ident) -> syn::Type {
             return pb_struct_ty;
         }
     }
-    ctxt.error_spanned_by(
-        ident,
-        format!("❌ Can't find {} protobuf struct", take_ident),
-    );
+    ctxt.error_spanned_by(ident, format!("❌ Can't find {} protobuf struct", take_ident));
     panic!()
 }
 

+ 1 - 3
rust-lib/flowy-ast/src/ctxt.rs

@@ -22,9 +22,7 @@ impl Ctxt {
             .push(syn::Error::new_spanned(obj.into_token_stream(), msg));
     }
 
-    pub fn syn_error(&self, err: syn::Error) {
-        self.errors.borrow_mut().as_mut().unwrap().push(err);
-    }
+    pub fn syn_error(&self, err: syn::Error) { self.errors.borrow_mut().as_mut().unwrap().push(err); }
 
     pub fn check(self) -> Result<(), Vec<syn::Error>> {
         let errors = self.errors.borrow_mut().take().unwrap();

+ 1 - 7
rust-lib/flowy-database/src/schema.rs

@@ -58,10 +58,4 @@ table! {
     }
 }
 
-allow_tables_to_appear_in_same_query!(
-    app_table,
-    doc_table,
-    user_table,
-    view_table,
-    workspace_table,
-);
+allow_tables_to_appear_in_same_query!(app_table, doc_table, user_table, view_table, workspace_table,);

+ 1 - 3
rust-lib/flowy-derive/src/dart_event/mod.rs

@@ -1,9 +1,7 @@
 use proc_macro2::TokenStream;
 
 // #[proc_macro_derive(DartEvent, attributes(event_ty))]
-pub fn expand_enum_derive(_input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
-    Ok(TokenStream::default())
-}
+pub fn expand_enum_derive(_input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> { Ok(TokenStream::default()) }
 
 // use flowy_ast::{ASTContainer, Ctxt};
 // use proc_macro2::TokenStream;

+ 2 - 4
rust-lib/flowy-derive/src/derive_cache/derive_cache.rs

@@ -69,8 +69,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "UserProfile"
         | "UpdateUserRequest"
         | "UpdateUserParams"
-        | "UserError"
-        => TypeCategory::Protobuf,
+        | "UserError" => TypeCategory::Protobuf,
         "ViewType"
         | "WorkspaceEvent"
         | "ErrorCode"
@@ -80,8 +79,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
         | "FFIStatusCode"
         | "UserStatus"
         | "UserEvent"
-        | "UserObservable"
-        => TypeCategory::Enum,
+        | "UserObservable" => TypeCategory::Enum,
 
         "Option" => TypeCategory::Opt,
         _ => TypeCategory::Primitive,

+ 3 - 9
rust-lib/flowy-derive/src/lib.rs

@@ -16,25 +16,19 @@ mod proto_buf;
 #[proc_macro_derive(ProtoBuf, attributes(pb))]
 pub fn derive_proto_buf(input: TokenStream) -> TokenStream {
     let input = parse_macro_input!(input as DeriveInput);
-    proto_buf::expand_derive(&input)
-        .unwrap_or_else(to_compile_errors)
-        .into()
+    proto_buf::expand_derive(&input).unwrap_or_else(to_compile_errors).into()
 }
 
 #[proc_macro_derive(ProtoBuf_Enum, attributes(pb))]
 pub fn derive_proto_buf_enum(input: TokenStream) -> TokenStream {
     let input = parse_macro_input!(input as DeriveInput);
-    proto_buf::expand_enum_derive(&input)
-        .unwrap_or_else(to_compile_errors)
-        .into()
+    proto_buf::expand_enum_derive(&input).unwrap_or_else(to_compile_errors).into()
 }
 
 #[proc_macro_derive(Flowy_Event, attributes(event, event_err))]
 pub fn derive_dart_event(input: TokenStream) -> TokenStream {
     let input = parse_macro_input!(input as DeriveInput);
-    dart_event::expand_enum_derive(&input)
-        .unwrap_or_else(to_compile_errors)
-        .into()
+    dart_event::expand_enum_derive(&input).unwrap_or_else(to_compile_errors).into()
 }
 
 fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {

+ 15 - 35
rust-lib/flowy-derive/src/proto_buf/deserialize.rs

@@ -6,20 +6,16 @@ pub fn make_de_token_steam(ctxt: &Ctxt, ast: &ASTContainer) -> Option<TokenStrea
     let pb_ty = ast.attrs.pb_struct_type()?;
     let struct_ident = &ast.ident;
 
-    let build_take_fields = ast
-        .data
-        .all_fields()
-        .filter(|f| !f.attrs.skip_deserializing())
-        .flat_map(|field| {
-            if let Some(func) = field.attrs.deserialize_with() {
-                let member = &field.member;
-                Some(quote! { o.#member=#struct_ident::#func(pb); })
-            } else if field.attrs.is_one_of() {
-                token_stream_for_one_of(ctxt, field)
-            } else {
-                token_stream_for_field(ctxt, &field.member, &field.ty, false)
-            }
-        });
+    let build_take_fields = ast.data.all_fields().filter(|f| !f.attrs.skip_deserializing()).flat_map(|field| {
+        if let Some(func) = field.attrs.deserialize_with() {
+            let member = &field.member;
+            Some(quote! { o.#member=#struct_ident::#func(pb); })
+        } else if field.attrs.is_one_of() {
+            token_stream_for_one_of(ctxt, field)
+        } else {
+            token_stream_for_field(ctxt, &field.member, &field.ty, false)
+        }
+    });
 
     let de_token_stream: TokenStream = quote! {
         impl std::convert::TryFrom<bytes::Bytes> for #struct_ident {
@@ -102,12 +98,7 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option<TokenStream>
     }
 }
 
-fn token_stream_for_field(
-    ctxt: &Ctxt,
-    member: &syn::Member,
-    ty: &syn::Type,
-    is_option: bool,
-) -> Option<TokenStream> {
+fn token_stream_for_field(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option: bool) -> Option<TokenStream> {
     let ident = get_member_ident(ctxt, member)?;
     let ty_info = parse_ty(ctxt, ty)?;
     match ident_category(ty_info.ident) {
@@ -142,8 +133,7 @@ fn token_stream_for_field(
             })
         },
         TypeCategory::Str => {
-            let take_ident =
-                syn::Ident::new(&format!("take_{}", ident.to_string()), Span::call_site());
+            let take_ident = syn::Ident::new(&format!("take_{}", ident.to_string()), Span::call_site());
             if is_option {
                 Some(quote! {
                     if pb.#member.is_empty() {
@@ -158,9 +148,7 @@ fn token_stream_for_field(
                 })
             }
         },
-        TypeCategory::Opt => {
-            token_stream_for_field(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
-        },
+        TypeCategory::Opt => token_stream_for_field(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true),
         TypeCategory::Primitive | TypeCategory::Bytes => {
             // eprintln!("😄 #{:?}", &field.name().unwrap());
             if is_option {
@@ -172,11 +160,7 @@ fn token_stream_for_field(
     }
 }
 
-fn token_stream_for_vec(
-    ctxt: &Ctxt,
-    member: &syn::Member,
-    bracketed_type: &TyInfo,
-) -> Option<TokenStream> {
+fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, bracketed_type: &TyInfo) -> Option<TokenStream> {
     let ident = get_member_ident(ctxt, member)?;
 
     match ident_category(bracketed_type.ident) {
@@ -208,11 +192,7 @@ fn token_stream_for_vec(
     }
 }
 
-fn token_stream_for_map(
-    ctxt: &Ctxt,
-    member: &syn::Member,
-    bracketed_type: &TyInfo,
-) -> Option<TokenStream> {
+fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, bracketed_type: &TyInfo) -> Option<TokenStream> {
     let ident = get_member_ident(ctxt, member)?;
 
     let take_ident = format_ident!("take_{}", ident.to_string());

+ 1 - 5
rust-lib/flowy-derive/src/proto_buf/mod.rs

@@ -3,11 +3,7 @@ mod enum_serde;
 mod serialize;
 mod util;
 
-use crate::proto_buf::{
-    deserialize::make_de_token_steam,
-    enum_serde::make_enum_token_stream,
-    serialize::make_se_token_stream,
-};
+use crate::proto_buf::{deserialize::make_de_token_steam, enum_serde::make_enum_token_stream, serialize::make_se_token_stream};
 use flowy_ast::*;
 use proc_macro2::TokenStream;
 

+ 4 - 15
rust-lib/flowy-derive/src/proto_buf/serialize.rs

@@ -76,18 +76,11 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option<TokenStream>
     }
 }
 
-fn gen_token_stream(
-    ctxt: &Ctxt,
-    member: &syn::Member,
-    ty: &syn::Type,
-    is_option: bool,
-) -> Option<TokenStream> {
+fn gen_token_stream(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option: bool) -> Option<TokenStream> {
     let ty_info = parse_ty(ctxt, ty)?;
     match ident_category(ty_info.ident) {
         TypeCategory::Array => token_stream_for_vec(ctxt, &member, &ty_info.ty),
-        TypeCategory::Map => {
-            token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap().ty)
-        },
+        TypeCategory::Map => token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap().ty),
         TypeCategory::Str => {
             if is_option {
                 Some(quote! {
@@ -100,12 +93,8 @@ fn gen_token_stream(
                 Some(quote! { pb.#member = self.#member.clone(); })
             }
         },
-        TypeCategory::Protobuf => Some(
-            quote! { pb.#member =  ::protobuf::SingularPtrField::some(self.#member.try_into().unwrap()); },
-        ),
-        TypeCategory::Opt => {
-            gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true)
-        },
+        TypeCategory::Protobuf => Some(quote! { pb.#member =  ::protobuf::SingularPtrField::some(self.#member.try_into().unwrap()); }),
+        TypeCategory::Opt => gen_token_stream(ctxt, member, ty_info.bracket_ty_info.unwrap().ty, true),
         TypeCategory::Enum => {
             // let pb_enum_ident = format_ident!("{}", ty_info.ident.to_string());
             // Some(quote! {

+ 1 - 4
rust-lib/flowy-derive/src/proto_buf/util.rs

@@ -17,9 +17,6 @@ pub(crate) fn get_member_ident<'a>(ctxt: &Ctxt, member: &'a syn::Member) -> Opti
 
 pub fn assert_bracket_ty_is_some(ctxt: &Ctxt, ty_info: &TyInfo) {
     if ty_info.bracket_ty_info.is_none() {
-        ctxt.error_spanned_by(
-            ty_info.ty,
-            format!("Invalid bracketed type when gen de token steam"),
-        );
+        ctxt.error_spanned_by(ty_info.ty, format!("Invalid bracketed type when gen de token steam"));
     }
 }

+ 2 - 6
rust-lib/flowy-dispatch/src/data.rs

@@ -37,9 +37,7 @@ where
             Payload::None => ready(Err(unexpected_none_payload(req))),
             Payload::Bytes(bytes) => match T::parse_from_bytes(bytes.clone()) {
                 Ok(data) => ready(Ok(Data(data))),
-                Err(e) => ready(Err(
-                    InternalError::DeserializeFromBytes(format!("{}", e)).into()
-                )),
+                Err(e) => ready(Err(InternalError::DeserializeFromBytes(format!("{}", e)).into())),
             },
         }
     }
@@ -78,9 +76,7 @@ where
     T: FromBytes,
 {
     match payload {
-        Payload::None => {
-            Err(InternalError::UnexpectedNone(format!("Parse fail, expected payload")).into())
-        },
+        Payload::None => Err(InternalError::UnexpectedNone(format!("Parse fail, expected payload")).into()),
         Payload::Bytes(bytes) => {
             let data = T::parse_from_bytes(bytes.clone())?;
             Ok(Data(data))

+ 1 - 9
rust-lib/flowy-dispatch/src/lib.rs

@@ -16,13 +16,5 @@ pub mod macros;
 pub use errors::Error;
 
 pub mod prelude {
-    pub use crate::{
-        byte_trait::*,
-        data::*,
-        dispatch::*,
-        errors::*,
-        module::*,
-        request::*,
-        response::*,
-    };
+    pub use crate::{byte_trait::*, data::*, dispatch::*, errors::*, module::*, request::*, response::*};
 }

+ 5 - 17
rust-lib/flowy-dispatch/src/module/container.rs

@@ -10,19 +10,13 @@ pub struct ModuleDataMap {
 
 impl ModuleDataMap {
     #[inline]
-    pub fn new() -> ModuleDataMap {
-        ModuleDataMap {
-            map: HashMap::default(),
-        }
-    }
+    pub fn new() -> ModuleDataMap { ModuleDataMap { map: HashMap::default() } }
 
     pub fn insert<T>(&mut self, val: T) -> Option<T>
     where
         T: 'static + Send + Sync,
     {
-        self.map
-            .insert(TypeId::of::<T>(), Box::new(val))
-            .and_then(downcast_owned)
+        self.map.insert(TypeId::of::<T>(), Box::new(val)).and_then(downcast_owned)
     }
 
     pub fn remove<T>(&mut self) -> Option<T>
@@ -36,18 +30,14 @@ impl ModuleDataMap {
     where
         T: 'static + Send + Sync,
     {
-        self.map
-            .get(&TypeId::of::<T>())
-            .and_then(|boxed| boxed.downcast_ref())
+        self.map.get(&TypeId::of::<T>()).and_then(|boxed| boxed.downcast_ref())
     }
 
     pub fn get_mut<T>(&mut self) -> Option<&mut T>
     where
         T: 'static + Send + Sync,
     {
-        self.map
-            .get_mut(&TypeId::of::<T>())
-            .and_then(|boxed| boxed.downcast_mut())
+        self.map.get_mut(&TypeId::of::<T>()).and_then(|boxed| boxed.downcast_mut())
     }
 
     pub fn contains<T>(&self) -> bool
@@ -60,6 +50,4 @@ impl ModuleDataMap {
     pub fn extend(&mut self, other: ModuleDataMap) { self.map.extend(other.map); }
 }
 
-fn downcast_owned<T: 'static + Send + Sync>(boxed: Box<dyn Any + Send + Sync>) -> Option<T> {
-    boxed.downcast().ok().map(|boxed| *boxed)
-}
+fn downcast_owned<T: 'static + Send + Sync>(boxed: Box<dyn Any + Send + Sync>) -> Option<T> { boxed.downcast().ok().map(|boxed| *boxed) }

+ 1 - 4
rust-lib/flowy-dispatch/src/module/data.rs

@@ -51,10 +51,7 @@ where
         if let Some(data) = req.module_data::<Unit<T>>() {
             ready(Ok(data.clone()))
         } else {
-            let msg = format!(
-                "Failed to get the module data of type: {}",
-                type_name::<T>()
-            );
+            let msg = format!("Failed to get the module data of type: {}", type_name::<T>());
             log::error!("{}", msg,);
             ready(Err(InternalError::Other(msg).into()))
         }

+ 1 - 3
rust-lib/flowy-dispatch/src/response/responder.rs

@@ -13,9 +13,7 @@ pub trait Responder {
 macro_rules! impl_responder {
     ($res: ty) => {
         impl Responder for $res {
-            fn respond_to(self, _: &EventRequest) -> EventResponse {
-                ResponseBuilder::Ok().data(self).build()
-            }
+            fn respond_to(self, _: &EventRequest) -> EventResponse { ResponseBuilder::Ok().data(self).build() }
         }
     };
 }

+ 3 - 9
rust-lib/flowy-dispatch/src/service/boxed.rs

@@ -44,11 +44,8 @@ where
     fn new_service(&self, cfg: Cfg) -> Self::Future { self.0.new_service(cfg) }
 }
 
-pub type BoxService<Req, Res, Err> = Box<
-    dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<'static, Result<Res, Err>>>
-        + Sync
-        + Send,
->;
+pub type BoxService<Req, Res, Err> =
+    Box<dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<'static, Result<Res, Err>>> + Sync + Send>;
 
 // #[allow(dead_code)]
 // pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
@@ -112,9 +109,6 @@ where
 
     fn new_service(&self, cfg: Cfg) -> Self::Future {
         let f = self.0.new_service(cfg);
-        Box::pin(async {
-            f.await
-                .map(|s| Box::new(ServiceWrapper::new(s)) as Self::Service)
-        })
+        Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as Self::Service) })
     }
 }

+ 1 - 3
rust-lib/flowy-dispatch/src/service/service.rs

@@ -41,9 +41,7 @@ pub struct ServiceResponse {
 }
 
 impl ServiceResponse {
-    pub fn new(request: EventRequest, response: EventResponse) -> Self {
-        ServiceResponse { request, response }
-    }
+    pub fn new(request: EventRequest, response: EventResponse) -> Self { ServiceResponse { request, response } }
 
     pub fn into_parts(self) -> (EventRequest, EventResponse) { (self.request, self.response) }
 }

+ 2 - 8
rust-lib/flowy-dispatch/src/system.rs

@@ -44,10 +44,7 @@ impl FlowySystem {
 
         let system = Self { sys_cmd_tx };
         FlowySystem::set_current(system);
-        let runner = SystemRunner {
-            rt: runtime,
-            stop_rx,
-        };
+        let runner = SystemRunner { rt: runtime, stop_rx };
         runner
     }
 
@@ -112,10 +109,7 @@ impl SystemRunner {
         match rt.block_on(stop_rx) {
             Ok(code) => {
                 if code != 0 {
-                    Err(io::Error::new(
-                        io::ErrorKind::Other,
-                        format!("Non-zero exit code: {}", code),
-                    ))
+                    Err(io::Error::new(io::ErrorKind::Other, format!("Non-zero exit code: {}", code)))
                 } else {
                     Ok(())
                 }

+ 2 - 10
rust-lib/flowy-dispatch/src/util/mod.rs

@@ -10,18 +10,10 @@ pub(crate) fn tokio_default_runtime() -> io::Result<tokio::runtime::Runtime> {
         .enable_io()
         .enable_time()
         .on_thread_start(move || {
-            log::trace!(
-                "{:?} thread started: thread_id= {}",
-                thread::current(),
-                thread_id::get()
-            );
+            log::trace!("{:?} thread started: thread_id= {}", thread::current(), thread_id::get());
         })
         .on_thread_stop(move || {
-            log::trace!(
-                "{:?} thread stopping: thread_id= {}",
-                thread::current(),
-                thread_id::get(),
-            );
+            log::trace!("{:?} thread stopping: thread_id= {}", thread::current(), thread_id::get(),);
         })
         .build()
 }

+ 1 - 1
rust-lib/flowy-dispatch/tests/api/helper.rs

@@ -1,10 +1,10 @@
+#[rustfmt::skip]
 use flowy_dispatch::prelude::*;
 use std::sync::Once;
 
 #[allow(dead_code)]
 pub fn setup_env() {
     static INIT: Once = Once::new();
-    std::env::);
     INIT.call_once(|| env_logger::init());
 }
 

+ 0 - 2
rust-lib/flowy-document/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 9 - 9
rust-lib/flowy-document/src/protobuf/model/mod.rs

@@ -1,13 +1,13 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod doc; 
-pub use doc::*; 
+mod doc;
+pub use doc::*;

+ 2 - 2
rust-lib/flowy-document/src/services/doc_controller.rs

@@ -32,7 +32,7 @@ impl DocController {
         Ok(())
     }
 
-    #[tracing::instrument(level = "debug", skip(self, conn), err)]
+    #[tracing::instrument(level = "debug", skip(self, conn, params), err)]
     pub fn update(&self, params: UpdateDocParams, conn: &SqliteConnection) -> Result<(), DocError> {
         let changeset = DocTableChangeset::new(params.clone());
         let _ = self.sql.update_doc_table(changeset, &*conn)?;
@@ -58,7 +58,7 @@ impl DocController {
 }
 
 impl DocController {
-    #[tracing::instrument(level = "debug", skip(self), err)]
+    #[tracing::instrument(level = "debug", skip(self, params), err)]
     fn update_doc_on_server(&self, params: UpdateDocParams) -> Result<(), DocError> {
         let token = self.user.token()?;
         let server = self.server.clone();

+ 0 - 2
rust-lib/flowy-infra/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 3 - 3
rust-lib/flowy-infra/src/protobuf/model/mod.rs

@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod kv; 
-pub use kv::*; 
+mod kv;
+pub use kv::*;

+ 1 - 1
rust-lib/flowy-log/src/layer.rs

@@ -4,7 +4,7 @@ use std::{fmt, io::Write};
 use tracing::{Event, Id, Subscriber};
 use tracing_bunyan_formatter::JsonStorage;
 use tracing_core::{metadata::Level, span::Attributes};
-use tracing_log::AsLog;
+
 use tracing_subscriber::{fmt::MakeWriter, layer::Context, registry::SpanRef, Layer};
 const LEVEL: &str = "level";
 const TIME: &str = "time";

+ 2 - 2
rust-lib/flowy-log/src/lib.rs

@@ -5,9 +5,9 @@ use std::path::Path;
 use tracing::subscriber::set_global_default;
 
 use crate::layer::*;
-use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
+use tracing_bunyan_formatter::JsonStorageLayer;
 use tracing_log::LogTracer;
-use tracing_subscriber::{fmt::format::FmtSpan, layer::SubscriberExt, EnvFilter};
+use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
 
 pub struct Builder {
     name: String,

+ 1 - 4
rust-lib/flowy-net/src/response/response.rs

@@ -16,10 +16,7 @@ impl FlowyResponse {
 
     pub fn success() -> Self { Self::new(Bytes::new(), None) }
 
-    pub fn data<T: TryInto<Bytes, Error = protobuf::ProtobufError>>(
-        mut self,
-        data: T,
-    ) -> Result<Self, ServerError> {
+    pub fn data<T: TryInto<Bytes, Error = protobuf::ProtobufError>>(mut self, data: T) -> Result<Self, ServerError> {
         let bytes: Bytes = data.try_into()?;
         self.data = bytes;
         Ok(self)

+ 2 - 2
rust-lib/flowy-net/src/response/response_serde.rs

@@ -50,7 +50,7 @@
 //                                 return
 // Err(de::Error::duplicate_field("data"));                             }
 //                             data = match
-// MapAccess::next_value::<DeserializeWith<T>>(&mut map) {                      
+// MapAccess::next_value::<DeserializeWith<T>>(&mut map) {
 // Ok(wrapper) => wrapper.value,                                 Err(err) =>
 // return Err(err),                             };
 //                         },
@@ -59,7 +59,7 @@
 //                 }
 //                 let msg = msg.ok_or_else(||
 // de::Error::missing_field("msg"))?;                 let code =
-// code.ok_or_else(|| de::Error::missing_field("code"))?;                 
+// code.ok_or_else(|| de::Error::missing_field("code"))?;
 // Ok(Self::Value::new(data, msg, code))             }
 //         }
 //         const FIELDS: &'static [&'static str] = &["msg", "code", "data"];

+ 0 - 2
rust-lib/flowy-observable/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 3 - 3
rust-lib/flowy-observable/src/protobuf/model/mod.rs

@@ -1,4 +1,4 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod subject; 
-pub use subject::*; 
+mod subject;
+pub use subject::*;

+ 1 - 0
rust-lib/flowy-ot/src/client/document/selection.rs

@@ -0,0 +1 @@
+

+ 1 - 6
rust-lib/flowy-ot/src/client/extensions/delete/default_delete.rs

@@ -8,11 +8,6 @@ impl DeleteExt for DefaultDelete {
     fn ext_name(&self) -> &str { "DefaultDelete" }
 
     fn apply(&self, _delta: &Delta, interval: Interval) -> Option<Delta> {
-        Some(
-            DeltaBuilder::new()
-                .retain(interval.start)
-                .delete(interval.size())
-                .build(),
-        )
+        Some(DeltaBuilder::new().retain(interval.start).delete(interval.size()).build())
     }
 }

+ 4 - 7
rust-lib/flowy-ot/src/client/extensions/delete/preserve_line_format_merge.rs

@@ -1,6 +1,6 @@
 use crate::{
     client::{extensions::DeleteExt, util::is_newline},
-    core::{Attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
+    core::{plain_attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
 };
 
 pub struct PreserveLineFormatOnMerge {}
@@ -22,10 +22,7 @@ impl DeleteExt for PreserveLineFormatOnMerge {
         }
 
         iter.seek::<CharMetric>(interval.size() - 1);
-        let mut new_delta = DeltaBuilder::new()
-            .retain(interval.start)
-            .delete(interval.size())
-            .build();
+        let mut new_delta = DeltaBuilder::new().retain(interval.start).delete(interval.size()).build();
 
         while iter.has_next() {
             match iter.next() {
@@ -34,7 +31,7 @@ impl DeleteExt for PreserveLineFormatOnMerge {
                     //
                     match op.get_data().find(NEW_LINE) {
                         None => {
-                            new_delta.retain(op.len(), Attributes::empty());
+                            new_delta.retain(op.len(), plain_attributes());
                             continue;
                         },
                         Some(line_break) => {
@@ -45,7 +42,7 @@ impl DeleteExt for PreserveLineFormatOnMerge {
                                 attributes.extend(newline_op.get_attributes());
                             }
 
-                            new_delta.retain(line_break, Attributes::empty());
+                            new_delta.retain(line_break, plain_attributes());
                             new_delta.retain(1, attributes);
                             break;
                         },

+ 4 - 4
rust-lib/flowy-ot/src/client/extensions/format/helper.rs

@@ -1,6 +1,6 @@
 use crate::{
     client::util::find_newline,
-    core::{Attribute, AttributeScope, Attributes, Delta, Operation},
+    core::{plain_attributes, Attribute, AttributeScope, Delta, Operation},
 };
 
 pub(crate) fn line_break(op: &Operation, attribute: &Attribute, scope: AttributeScope) -> Delta {
@@ -13,10 +13,10 @@ pub(crate) fn line_break(op: &Operation, attribute: &Attribute, scope: Attribute
         match scope {
             AttributeScope::Inline => {
                 new_delta.retain(line_break - start, attribute.clone().into());
-                new_delta.retain(1, Attributes::empty());
+                new_delta.retain(1, plain_attributes());
             },
             AttributeScope::Block => {
-                new_delta.retain(line_break - start, Attributes::empty());
+                new_delta.retain(line_break - start, plain_attributes());
                 new_delta.retain(1, attribute.clone().into());
             },
             _ => {
@@ -31,7 +31,7 @@ pub(crate) fn line_break(op: &Operation, attribute: &Attribute, scope: Attribute
     if start < end {
         match scope {
             AttributeScope::Inline => new_delta.retain(end - start, attribute.clone().into()),
-            AttributeScope::Block => new_delta.retain(end - start, Attributes::empty()),
+            AttributeScope::Block => new_delta.retain(end - start, plain_attributes()),
             _ => log::error!("Unsupported parser line break for {:?}", scope),
         }
     }

+ 5 - 7
rust-lib/flowy-ot/src/client/extensions/format/resolve_block_format.rs

@@ -3,7 +3,7 @@ use crate::{
         extensions::{format::helper::line_break, FormatExt},
         util::find_newline,
     },
-    core::{Attribute, AttributeScope, Attributes, Delta, DeltaBuilder, DeltaIter, Interval},
+    core::{plain_attributes, Attribute, AttributeScope, Delta, DeltaBuilder, DeltaIter, Interval},
 };
 
 pub struct ResolveBlockFormat {}
@@ -22,7 +22,7 @@ impl FormatExt for ResolveBlockFormat {
         while start < end && iter.has_next() {
             let next_op = iter.next_op_with_len(end - start).unwrap();
             match find_newline(next_op.get_data()) {
-                None => new_delta.retain(next_op.len(), Attributes::empty()),
+                None => new_delta.retain(next_op.len(), plain_attributes()),
                 Some(_) => {
                     let tmp_delta = line_break(&next_op, attribute, AttributeScope::Block);
                     new_delta.extend(tmp_delta);
@@ -33,14 +33,12 @@ impl FormatExt for ResolveBlockFormat {
         }
 
         while iter.has_next() {
-            let op = iter
-                .next_op()
-                .expect("Unexpected None, iter.has_next() must return op");
+            let op = iter.next_op().expect("Unexpected None, iter.has_next() must return op");
 
             match find_newline(op.get_data()) {
-                None => new_delta.retain(op.len(), Attributes::empty()),
+                None => new_delta.retain(op.len(), plain_attributes()),
                 Some(line_break) => {
-                    new_delta.retain(line_break, Attributes::empty());
+                    new_delta.retain(line_break, plain_attributes());
                     new_delta.retain(1, attribute.clone().into());
                     break;
                 },

+ 3 - 3
rust-lib/flowy-ot/src/client/extensions/insert/auto_format.rs

@@ -31,7 +31,7 @@ impl InsertExt for AutoFormatExt {
                     });
 
                     let next_attributes = match iter.next_op() {
-                        None => Attributes::empty(),
+                        None => plain_attributes(),
                         Some(op) => op.get_attributes(),
                     };
 
@@ -50,7 +50,7 @@ impl InsertExt for AutoFormatExt {
     }
 }
 
-use crate::core::{AttributeBuilder, Attributes, DeltaBuilder};
+use crate::core::{plain_attributes, Attribute, Attributes, DeltaBuilder};
 use bytecount::num_chars;
 use std::cmp::min;
 use url::Url;
@@ -62,7 +62,7 @@ pub enum AutoFormatter {
 impl AutoFormatter {
     pub fn to_attributes(&self) -> Attributes {
         match self {
-            AutoFormatter::Url(url) => AttributeBuilder::new().link(url.as_str(), true).build(),
+            AutoFormatter::Url(url) => Attribute::Link(url.as_str()).into(),
         }
     }
 

+ 2 - 18
rust-lib/flowy-ot/src/client/extensions/insert/mod.rs

@@ -18,28 +18,12 @@ pub struct InsertEmbedsExt {}
 impl InsertExt for InsertEmbedsExt {
     fn ext_name(&self) -> &str { "InsertEmbedsExt" }
 
-    fn apply(
-        &self,
-        _delta: &Delta,
-        _replace_len: usize,
-        _text: &str,
-        _index: usize,
-    ) -> Option<Delta> {
-        None
-    }
+    fn apply(&self, _delta: &Delta, _replace_len: usize, _text: &str, _index: usize) -> Option<Delta> { None }
 }
 
 pub struct ForceNewlineForInsertsAroundEmbedExt {}
 impl InsertExt for ForceNewlineForInsertsAroundEmbedExt {
     fn ext_name(&self) -> &str { "ForceNewlineForInsertsAroundEmbedExt" }
 
-    fn apply(
-        &self,
-        _delta: &Delta,
-        _replace_len: usize,
-        _text: &str,
-        _index: usize,
-    ) -> Option<Delta> {
-        None
-    }
+    fn apply(&self, _delta: &Delta, _replace_len: usize, _text: &str, _index: usize) -> Option<Delta> { None }
 }

+ 5 - 13
rust-lib/flowy-ot/src/client/extensions/insert/preserve_block_format.rs

@@ -1,14 +1,6 @@
 use crate::{
     client::{extensions::InsertExt, util::is_newline},
-    core::{
-        attributes_except_header,
-        AttributeKey,
-        Attributes,
-        Delta,
-        DeltaBuilder,
-        DeltaIter,
-        NEW_LINE,
-    },
+    core::{attributes_except_header, plain_attributes, Attribute, AttributeKey, Attributes, Delta, DeltaBuilder, DeltaIter, NEW_LINE},
 };
 
 pub struct PreserveBlockFormatOnInsert {}
@@ -32,14 +24,14 @@ impl InsertExt for PreserveBlockFormatOnInsert {
 
                 let mut reset_attribute = Attributes::new();
                 if newline_attributes.contains_key(&AttributeKey::Header) {
-                    reset_attribute.add(AttributeKey::Header.value(""));
+                    reset_attribute.add(Attribute::Header(1));
                 }
 
                 let lines: Vec<_> = text.split(NEW_LINE).collect();
                 let mut new_delta = DeltaBuilder::new().retain(index + replace_len).build();
                 lines.iter().enumerate().for_each(|(i, line)| {
                     if !line.is_empty() {
-                        new_delta.insert(line, Attributes::empty());
+                        new_delta.insert(line, plain_attributes());
                     }
 
                     if i == 0 {
@@ -51,9 +43,9 @@ impl InsertExt for PreserveBlockFormatOnInsert {
                     }
                 });
                 if !reset_attribute.is_empty() {
-                    new_delta.retain(offset, Attributes::empty());
+                    new_delta.retain(offset, plain_attributes());
                     let len = newline_op.get_data().find(NEW_LINE).unwrap();
-                    new_delta.retain(len, Attributes::empty());
+                    new_delta.retain(len, plain_attributes());
                     new_delta.retain(1, reset_attribute.clone());
                 }
 

+ 5 - 5
rust-lib/flowy-ot/src/client/extensions/insert/preserve_inline_format.rs

@@ -3,7 +3,7 @@ use crate::{
         extensions::InsertExt,
         util::{contain_newline, is_newline},
     },
-    core::{AttributeKey, Attributes, Delta, DeltaBuilder, DeltaIter, OpNewline, NEW_LINE},
+    core::{plain_attributes, AttributeKey, Delta, DeltaBuilder, DeltaIter, OpNewline, NEW_LINE},
 };
 
 pub struct PreserveInlineFormat {}
@@ -33,10 +33,10 @@ impl InsertExt for PreserveInlineFormat {
 
         let next = iter.next_op();
         match &next {
-            None => attributes = Attributes::empty(),
+            None => attributes = plain_attributes(),
             Some(next) => {
                 if OpNewline::parse(&next).is_equal() {
-                    attributes = Attributes::empty();
+                    attributes = plain_attributes();
                 }
             },
         }
@@ -72,11 +72,11 @@ impl InsertExt for PreserveLineFormatOnSplit {
         }
 
         let mut new_delta = Delta::new();
-        new_delta.retain(index + replace_len, Attributes::empty());
+        new_delta.retain(index + replace_len, plain_attributes());
 
         if newline_status.is_contain() {
             debug_assert!(next.has_attribute() == false);
-            new_delta.insert(NEW_LINE, Attributes::empty());
+            new_delta.insert(NEW_LINE, plain_attributes());
             return Some(new_delta);
         }
 

+ 1 - 1
rust-lib/flowy-ot/src/client/extensions/insert/reset_format_on_new_line.rs

@@ -21,7 +21,7 @@ impl InsertExt for ResetLineFormatOnNewLine {
 
         let mut reset_attribute = Attributes::new();
         if next_op.get_attributes().contains_key(&AttributeKey::Header) {
-            reset_attribute.add(AttributeKey::Header.value(""));
+            reset_attribute.mark_as_removed(&AttributeKey::Header);
         }
 
         let len = index + replace_len;

+ 1 - 6
rust-lib/flowy-ot/src/client/history.rs

@@ -22,12 +22,7 @@ pub struct UndoResult {
 }
 
 impl UndoResult {
-    pub fn fail() -> Self {
-        UndoResult {
-            success: false,
-            len: 0,
-        }
-    }
+    pub fn fail() -> Self { UndoResult { success: false, len: 0 } }
 
     pub fn success(len: usize) -> Self { UndoResult { success: true, len } }
 }

+ 3 - 18
rust-lib/flowy-ot/src/client/view.rs

@@ -21,12 +21,7 @@ impl View {
         }
     }
 
-    pub(crate) fn insert(
-        &self,
-        delta: &Delta,
-        text: &str,
-        interval: Interval,
-    ) -> Result<Delta, OTError> {
+    pub(crate) fn insert(&self, delta: &Delta, text: &str, interval: Interval) -> Result<Delta, OTError> {
         let mut new_delta = None;
         for ext in &self.insert_exts {
             if let Some(delta) = ext.apply(delta, interval.size(), text, interval.start) {
@@ -58,12 +53,7 @@ impl View {
         }
     }
 
-    pub(crate) fn format(
-        &self,
-        delta: &Delta,
-        attribute: Attribute,
-        interval: Interval,
-    ) -> Result<Delta, OTError> {
+    pub(crate) fn format(&self, delta: &Delta, attribute: Attribute, interval: Interval) -> Result<Delta, OTError> {
         let mut new_delta = None;
         for ext in &self.format_exts {
             if let Some(delta) = ext.apply(delta, interval, &attribute) {
@@ -102,9 +92,4 @@ fn construct_format_exts() -> Vec<FormatExtension> {
     ]
 }
 
-fn construct_delete_exts() -> Vec<DeleteExtension> {
-    vec![
-        Box::new(PreserveLineFormatOnMerge {}),
-        Box::new(DefaultDelete {}),
-    ]
-}
+fn construct_delete_exts() -> Vec<DeleteExtension> { vec![Box::new(PreserveLineFormatOnMerge {}), Box::new(DefaultDelete {})] }

+ 98 - 88
rust-lib/flowy-ot/src/core/attributes/attribute.rs

@@ -1,3 +1,4 @@
+#![allow(non_snake_case)]
 use crate::core::{Attributes, REMOVE_FLAG};
 use derive_more::Display;
 use lazy_static::lazy_static;
@@ -31,8 +32,7 @@ lazy_static! {
         AttributeKey::Size,
         AttributeKey::Background,
     ]);
-    static ref INGORE_KEYS: HashSet<AttributeKey> =
-        HashSet::from_iter(vec![AttributeKey::Width, AttributeKey::Height,]);
+    static ref INGORE_KEYS: HashSet<AttributeKey> = HashSet::from_iter(vec![AttributeKey::Width, AttributeKey::Height,]);
 }
 
 #[derive(Debug, PartialEq, Eq, Clone)]
@@ -43,6 +43,51 @@ pub enum AttributeScope {
     Ignore,
 }
 
+macro_rules! inline_attribute {
+    (
+        $key: ident,
+        $value: ty
+    ) => {
+        pub fn $key(value: $value) -> Self {
+            Self {
+                key: AttributeKey::$key,
+                value: value.into(),
+                scope: AttributeScope::Inline,
+            }
+        }
+    };
+}
+
+macro_rules! block_attribute {
+    (
+        $key: ident,
+        $value: ident
+    ) => {
+        pub fn $key(value: $value) -> Self {
+            Self {
+                key: AttributeKey::$key,
+                value: value.into(),
+                scope: AttributeScope::Block,
+            }
+        }
+    };
+}
+
+macro_rules! ignore_attribute {
+    (
+        $key: ident,
+        $value: ident
+    ) => {
+        pub fn $key(value: $value) -> Self {
+            Self {
+                key: AttributeKey::$key,
+                value: value.into(),
+                scope: AttributeScope::Ignore,
+            }
+        }
+    };
+}
+
 #[derive(Debug, Clone)]
 pub struct Attribute {
     pub key: AttributeKey,
@@ -50,6 +95,36 @@ pub struct Attribute {
     pub scope: AttributeScope,
 }
 
+impl Attribute {
+    inline_attribute!(Bold, bool);
+    inline_attribute!(Italic, bool);
+    inline_attribute!(Underline, bool);
+    inline_attribute!(StrikeThrough, bool);
+    inline_attribute!(Link, &str);
+    inline_attribute!(Color, String);
+    inline_attribute!(Font, usize);
+    inline_attribute!(Size, usize);
+    inline_attribute!(Background, String);
+
+    block_attribute!(Header, usize);
+    block_attribute!(LeftAlignment, usize);
+    block_attribute!(CenterAlignment, usize);
+    block_attribute!(RightAlignment, usize);
+    block_attribute!(JustifyAlignment, bool);
+    block_attribute!(Indent, String);
+    block_attribute!(Align, String);
+    block_attribute!(CodeBlock, String);
+    block_attribute!(List, String);
+    block_attribute!(Bullet, bool);
+    block_attribute!(Ordered, bool);
+    block_attribute!(Checked, bool);
+    block_attribute!(UnChecked, bool);
+    block_attribute!(QuoteBlock, bool);
+
+    ignore_attribute!(Width, usize);
+    ignore_attribute!(Height, usize);
+}
+
 impl fmt::Display for Attribute {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         let s = format!("{:?}:{} {:?}", self.key, self.value.as_ref(), self.scope);
@@ -120,91 +195,6 @@ pub enum AttributeKey {
     UnChecked,
 }
 
-impl AttributeKey {
-    pub fn remove(&self) -> Attribute { self.value(REMOVE_FLAG) }
-
-    pub fn value<T: Into<AttributeValue>>(&self, value: T) -> Attribute {
-        let key = self.clone();
-        let value: AttributeValue = value.into();
-        debug_assert_eq!(self.check_value(&value), true);
-
-        if INLINE_KEYS.contains(self) {
-            return Attribute {
-                key,
-                value,
-                scope: AttributeScope::Inline,
-            };
-        }
-
-        if BLOCK_KEYS.contains(self) {
-            return Attribute {
-                key,
-                value,
-                scope: AttributeScope::Block,
-            };
-        }
-
-        Attribute {
-            key,
-            value,
-            scope: AttributeScope::Ignore,
-        }
-    }
-
-    fn check_value(&self, value: &AttributeValue) -> bool {
-        if value.0.is_empty() {
-            return true;
-        }
-
-        match self {
-            AttributeKey::Bold
-            | AttributeKey::Italic
-            | AttributeKey::Underline
-            | AttributeKey::StrikeThrough
-            | AttributeKey::Indent
-            | AttributeKey::Align
-            | AttributeKey::CodeBlock
-            | AttributeKey::List
-            | AttributeKey::QuoteBlock
-            | AttributeKey::JustifyAlignment
-            | AttributeKey::Bullet
-            | AttributeKey::Ordered
-            | AttributeKey::Checked
-            | AttributeKey::UnChecked => {
-                if let Err(e) = value.0.parse::<bool>() {
-                    log::error!(
-                        "Parser failed: {:?}. expected bool, but receive {}",
-                        e,
-                        value.0
-                    );
-                    return false;
-                }
-            },
-
-            AttributeKey::Link | AttributeKey::Color | AttributeKey::Background => {},
-
-            AttributeKey::Header
-            | AttributeKey::Width
-            | AttributeKey::Height
-            | AttributeKey::Font
-            | AttributeKey::Size
-            | AttributeKey::LeftAlignment
-            | AttributeKey::CenterAlignment
-            | AttributeKey::RightAlignment => {
-                if let Err(e) = value.0.parse::<usize>() {
-                    log::error!(
-                        "Parser failed: {:?}. expected usize, but receive {}",
-                        e,
-                        value.0
-                    );
-                    return false;
-                }
-            },
-        }
-        true
-    }
-}
-
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct AttributeValue(pub(crate) String);
 
@@ -213,13 +203,33 @@ impl AsRef<str> for AttributeValue {
 }
 
 impl std::convert::From<&usize> for AttributeValue {
-    fn from(val: &usize) -> Self { AttributeValue(format!("{}", val)) }
+    fn from(val: &usize) -> Self {
+        if *val > (0 as usize) {
+            AttributeValue(format!("{}", val))
+        } else {
+            AttributeValue(format!(""))
+        }
+    }
+}
+
+impl std::convert::From<usize> for AttributeValue {
+    fn from(val: usize) -> Self {
+        if val > (0 as usize) {
+            AttributeValue(format!("{}", val))
+        } else {
+            AttributeValue(format!(""))
+        }
+    }
 }
 
 impl std::convert::From<&str> for AttributeValue {
     fn from(val: &str) -> Self { AttributeValue(val.to_owned()) }
 }
 
+impl std::convert::From<String> for AttributeValue {
+    fn from(val: String) -> Self { AttributeValue(val) }
+}
+
 impl std::convert::From<bool> for AttributeValue {
     fn from(val: bool) -> Self {
         let val = match val {

+ 27 - 34
rust-lib/flowy-ot/src/core/attributes/attributes.rs

@@ -4,36 +4,34 @@ use std::{collections::HashMap, fmt};
 pub const REMOVE_FLAG: &'static str = "";
 pub(crate) fn should_remove(val: &AttributeValue) -> bool { val.0 == REMOVE_FLAG }
 
-#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
 pub struct Attributes {
     #[serde(skip_serializing_if = "HashMap::is_empty")]
     #[serde(flatten)]
     pub(crate) inner: HashMap<AttributeKey, AttributeValue>,
 }
 
-impl fmt::Display for Attributes {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_fmt(format_args!("{:?}", self.inner))
+impl std::default::Default for Attributes {
+    fn default() -> Self {
+        Self {
+            inner: HashMap::with_capacity(0),
+        }
     }
 }
 
-impl Attributes {
-    pub fn new() -> Self {
-        Attributes {
-            inner: HashMap::new(),
-        }
-    }
+impl fmt::Display for Attributes {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.inner)) }
+}
 
-    pub fn empty() -> Self { Self::default() }
+pub fn plain_attributes() -> Attributes { Attributes::default() }
+
+impl Attributes {
+    pub fn new() -> Self { Attributes { inner: HashMap::new() } }
 
     pub fn is_empty(&self) -> bool { self.inner.is_empty() }
 
     pub fn add(&mut self, attribute: Attribute) {
-        let Attribute {
-            key,
-            value,
-            scope: _,
-        } = attribute;
+        let Attribute { key, value, scope: _ } = attribute;
         self.inner.insert(key, value);
     }
 
@@ -45,9 +43,7 @@ impl Attributes {
     pub fn mark_all_as_removed_except(&mut self, attribute: Option<AttributeKey>) {
         match attribute {
             None => {
-                self.inner
-                    .iter_mut()
-                    .for_each(|(_k, v)| v.0 = REMOVE_FLAG.into());
+                self.inner.iter_mut().for_each(|(_k, v)| v.0 = REMOVE_FLAG.into());
             },
             Some(attribute) => {
                 self.inner.iter_mut().for_each(|(k, v)| {
@@ -153,24 +149,21 @@ pub fn transform_operation(left: &Option<Operation>, right: &Option<Operation>)
 
     let left = attr_l.unwrap();
     let right = attr_r.unwrap();
-    left.iter()
-        .fold(Attributes::new(), |mut new_attributes, (k, v)| {
-            if !right.contains_key(k) {
-                new_attributes.insert(k.clone(), v.clone());
-            }
-            new_attributes
-        })
+    left.iter().fold(Attributes::new(), |mut new_attributes, (k, v)| {
+        if !right.contains_key(k) {
+            new_attributes.insert(k.clone(), v.clone());
+        }
+        new_attributes
+    })
 }
 
 pub fn invert_attributes(attr: Attributes, base: Attributes) -> Attributes {
-    let base_inverted = base
-        .iter()
-        .fold(Attributes::new(), |mut attributes, (k, v)| {
-            if base.get(k) != attr.get(k) && attr.contains_key(k) {
-                attributes.insert(k.clone(), v.clone());
-            }
-            attributes
-        });
+    let base_inverted = base.iter().fold(Attributes::new(), |mut attributes, (k, v)| {
+        if base.get(k) != attr.get(k) && attr.contains_key(k) {
+            attributes.insert(k.clone(), v.clone());
+        }
+        attributes
+    });
 
     let inverted = attr.iter().fold(base_inverted, |mut attributes, (k, _)| {
         if base.get(k) != attr.get(k) && !base.contains_key(k) {

+ 1 - 3
rust-lib/flowy-ot/src/core/attributes/attributes_serde.rs

@@ -21,9 +21,7 @@ impl<'de> Deserialize<'de> for AttributeValue {
         impl<'de> Visitor<'de> for OperationSeqVisitor {
             type Value = AttributeValue;
 
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-                formatter.write_str("a string")
-            }
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string") }
 
             fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
             where

+ 2 - 44
rust-lib/flowy-ot/src/core/attributes/builder.rs

@@ -1,33 +1,9 @@
-use crate::core::{Attribute, AttributeKey, AttributeValue, Attributes, REMOVE_FLAG};
-
+#![allow(non_snake_case)]
+use crate::core::{Attribute, Attributes};
 pub struct AttributeBuilder {
     inner: Attributes,
 }
 
-macro_rules! impl_bool_attribute {
-    ($name: ident,$key: expr) => {
-        pub fn $name(self, value: bool) -> Self {
-            let value = match value {
-                true => "true",
-                false => REMOVE_FLAG,
-            };
-            self.insert($key, value)
-        }
-    };
-}
-
-macro_rules! impl_str_attribute {
-    ($name: ident,$key: expr) => {
-        pub fn $name(self, s: &str, value: bool) -> Self {
-            let value = match value {
-                true => s,
-                false => REMOVE_FLAG,
-            };
-            self.insert($key, value)
-        }
-    };
-}
-
 impl AttributeBuilder {
     pub fn new() -> Self {
         Self {
@@ -40,23 +16,5 @@ impl AttributeBuilder {
         self
     }
 
-    pub fn insert<T: Into<AttributeValue>>(mut self, key: AttributeKey, value: T) -> Self {
-        self.inner.add(key.value(value));
-        self
-    }
-
-    pub fn remove<T: Into<String>>(mut self, key: AttributeKey) -> Self {
-        self.inner.add(key.value(REMOVE_FLAG));
-        self
-    }
-
-    // AttributeBuilder::new().bold(true).build()
-    impl_bool_attribute!(bold, AttributeKey::Bold);
-    impl_bool_attribute!(italic, AttributeKey::Italic);
-    impl_bool_attribute!(underline, AttributeKey::Underline);
-    impl_bool_attribute!(strike_through, AttributeKey::StrikeThrough);
-    impl_str_attribute!(link, AttributeKey::Link);
-    // impl_str_attribute!(header, AttributeKey::Header);
-
     pub fn build(self) -> Attributes { self.inner }
 }

+ 4 - 8
rust-lib/flowy-ot/src/core/delta/builder.rs

@@ -1,15 +1,11 @@
-use crate::core::{Attributes, Delta, Operation};
+use crate::core::{plain_attributes, Attributes, Delta, Operation};
 
 pub struct DeltaBuilder {
     delta: Delta,
 }
 
 impl DeltaBuilder {
-    pub fn new() -> Self {
-        Self {
-            delta: Delta::new(),
-        }
-    }
+    pub fn new() -> Self { Self { delta: Delta::new() } }
 
     pub fn retain_with_attributes(mut self, n: usize, attrs: Attributes) -> Self {
         self.delta.retain(n, attrs);
@@ -17,7 +13,7 @@ impl DeltaBuilder {
     }
 
     pub fn retain(mut self, n: usize) -> Self {
-        self.delta.retain(n, Attributes::empty());
+        self.delta.retain(n, plain_attributes());
         self
     }
 
@@ -32,7 +28,7 @@ impl DeltaBuilder {
     }
 
     pub fn insert(mut self, s: &str) -> Self {
-        self.delta.insert(s, Attributes::empty());
+        self.delta.insert(s, plain_attributes());
         self
     }
 

+ 2 - 6
rust-lib/flowy-ot/src/core/delta/cursor.rs

@@ -50,9 +50,7 @@ impl<'a> OpCursor<'a> {
         let mut consume_len = 0;
         while find_op.is_none() && next_op.is_some() {
             let op = next_op.take().unwrap();
-            let interval = self
-                .next_iv_before(force_end)
-                .unwrap_or(Interval::new(0, 0));
+            let interval = self.next_iv_before(force_end).unwrap_or(Interval::new(0, 0));
 
             // cache the op if the interval is empty. e.g. last_op_before(Some(0))
             if interval.is_empty() {
@@ -188,9 +186,7 @@ fn check_bound(current: usize, target: usize) -> Result<(), OTError> {
     debug_assert!(current <= target);
     if current > target {
         let msg = format!("{} should be greater than current: {}", target, current);
-        return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength)
-            .msg(&msg)
-            .build());
+        return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).msg(&msg).build());
     }
     Ok(())
 }

+ 8 - 8
rust-lib/flowy-ot/src/core/delta/delta.rs

@@ -102,7 +102,7 @@ impl Delta {
         }
     }
 
-    pub fn insert(&mut self, s: &str, attrs: Attributes) {
+    pub fn insert(&mut self, s: &str, attributes: Attributes) {
         if s.is_empty() {
             return;
         }
@@ -111,18 +111,18 @@ impl Delta {
         let new_last = match self.ops.as_mut_slice() {
             [.., Operation::Insert(insert)] => {
                 //
-                insert.merge_or_new_op(s, attrs)
+                insert.merge_or_new_op(s, attributes)
             },
             [.., Operation::Insert(pre_insert), Operation::Delete(_)] => {
                 //
-                pre_insert.merge_or_new_op(s, attrs)
+                pre_insert.merge_or_new_op(s, attributes)
             },
             [.., op_last @ Operation::Delete(_)] => {
                 let new_last = op_last.clone();
-                *op_last = OpBuilder::insert(s).attributes(attrs).build();
+                *op_last = OpBuilder::insert(s).attributes(attributes).build();
                 Some(new_last)
             },
-            _ => Some(OpBuilder::insert(s).attributes(attrs).build()),
+            _ => Some(OpBuilder::insert(s).attributes(attributes).build()),
         };
 
         match new_last {
@@ -131,7 +131,7 @@ impl Delta {
         }
     }
 
-    pub fn retain(&mut self, n: usize, attrs: Attributes) {
+    pub fn retain(&mut self, n: usize, attributes: Attributes) {
         if n == 0 {
             return;
         }
@@ -139,11 +139,11 @@ impl Delta {
         self.target_len += n as usize;
 
         if let Some(Operation::Retain(retain)) = self.ops.last_mut() {
-            if let Some(new_op) = retain.merge_or_new_op(n, attrs) {
+            if let Some(new_op) = retain.merge_or_new(n, attributes) {
                 self.ops.push(new_op);
             }
         } else {
-            self.ops.push(OpBuilder::retain(n).attributes(attrs).build());
+            self.ops.push(OpBuilder::retain(n).attributes(attributes).build());
         }
     }
 

+ 1 - 3
rust-lib/flowy-ot/src/core/delta/delta_serde.rs

@@ -32,9 +32,7 @@ impl<'de> Deserialize<'de> for Delta {
         impl<'de> Visitor<'de> for OperationSeqVisitor {
             type Value = Delta;
 
-            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-                formatter.write_str("a sequence")
-            }
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") }
 
             fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
             where

+ 2 - 6
rust-lib/flowy-ot/src/core/delta/iterator.rs

@@ -39,9 +39,7 @@ impl<'a> DeltaIter<'a> {
 
     pub fn next_op(&mut self) -> Option<Operation> { self.cursor.next() }
 
-    pub fn next_op_with_len(&mut self, len: usize) -> Option<Operation> {
-        self.cursor.next_with_len(Some(len))
-    }
+    pub fn next_op_with_len(&mut self, len: usize) -> Option<Operation> { self.cursor.next_with_len(Some(len)) }
 
     // find next op contains NEW_LINE
     pub fn next_op_with_newline(&mut self) -> Option<(Operation, usize)> {
@@ -210,9 +208,7 @@ impl OpNewline {
 
     pub fn is_not_found(&self) -> bool { self == &OpNewline::NotFound }
 
-    pub fn is_contain(&self) -> bool {
-        self.is_start() || self.is_end() || self.is_equal() || self == &OpNewline::Contain
-    }
+    pub fn is_contain(&self) -> bool { self.is_start() || self.is_end() || self.is_equal() || self == &OpNewline::Contain }
 
     pub fn is_equal(&self) -> bool { self == &OpNewline::Equal }
 }

+ 8 - 27
rust-lib/flowy-ot/src/core/interval.rs

@@ -33,9 +33,7 @@ impl Interval {
 
     pub fn contains(&self, val: usize) -> bool { self.start <= val && val < self.end }
 
-    pub fn contains_range(&self, start: usize, end: usize) -> bool {
-        !self.intersect(Interval::new(start, end)).is_empty()
-    }
+    pub fn contains_range(&self, start: usize, end: usize) -> bool { !self.intersect(Interval::new(start, end)).is_empty() }
 
     pub fn is_after(&self, val: usize) -> bool { self.start > val }
 
@@ -101,9 +99,7 @@ impl std::default::Default for Interval {
 }
 
 impl fmt::Display for Interval {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "[{}, {})", self.start(), self.end())
-    }
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[{}, {})", self.start(), self.end()) }
 }
 
 impl fmt::Debug for Interval {
@@ -122,15 +118,11 @@ impl From<RangeTo<usize>> for Interval {
 }
 
 impl From<RangeInclusive<usize>> for Interval {
-    fn from(src: RangeInclusive<usize>) -> Interval {
-        Interval::new(*src.start(), src.end().saturating_add(1))
-    }
+    fn from(src: RangeInclusive<usize>) -> Interval { Interval::new(*src.start(), src.end().saturating_add(1)) }
 }
 
 impl From<RangeToInclusive<usize>> for Interval {
-    fn from(src: RangeToInclusive<usize>) -> Interval {
-        Interval::new(0, src.end.saturating_add(1))
-    }
+    fn from(src: RangeToInclusive<usize>) -> Interval { Interval::new(0, src.end.saturating_add(1)) }
 }
 
 #[cfg(test)]
@@ -186,29 +178,18 @@ mod tests {
 
     #[test]
     fn intersect() {
-        assert_eq!(
-            Interval::new(2, 3),
-            Interval::new(1, 3).intersect(Interval::new(2, 4))
-        );
-        assert!(Interval::new(1, 2)
-            .intersect(Interval::new(2, 43))
-            .is_empty());
+        assert_eq!(Interval::new(2, 3), Interval::new(1, 3).intersect(Interval::new(2, 4)));
+        assert!(Interval::new(1, 2).intersect(Interval::new(2, 43)).is_empty());
     }
 
     #[test]
     fn prefix() {
-        assert_eq!(
-            Interval::new(1, 2),
-            Interval::new(1, 4).prefix(Interval::new(2, 3))
-        );
+        assert_eq!(Interval::new(1, 2), Interval::new(1, 4).prefix(Interval::new(2, 3)));
     }
 
     #[test]
     fn suffix() {
-        assert_eq!(
-            Interval::new(3, 4),
-            Interval::new(1, 4).suffix(Interval::new(2, 3))
-        );
+        assert_eq!(Interval::new(3, 4), Interval::new(1, 4).suffix(Interval::new(2, 3)));
     }
 
     #[test]

+ 8 - 31
rust-lib/flowy-ot/src/core/operation/operation.rs

@@ -42,9 +42,7 @@ impl Operation {
 
     pub fn has_attribute(&self) -> bool { !self.get_attributes().is_empty() }
 
-    pub fn contain_attribute(&self, attribute: &Attribute) -> bool {
-        self.get_attributes().contains_key(&attribute.key)
-    }
+    pub fn contain_attribute(&self, attribute: &Attribute) -> bool { self.get_attributes().contains_key(&attribute.key) }
 
     pub fn len(&self) -> usize {
         match self {
@@ -72,11 +70,7 @@ impl Operation {
             },
             Operation::Insert(insert) => {
                 let attributes = self.get_attributes();
-                left = Some(
-                    OpBuilder::insert(&insert.s[0..index])
-                        .attributes(attributes.clone())
-                        .build(),
-                );
+                left = Some(OpBuilder::insert(&insert.s[0..index]).attributes(attributes.clone()).build());
                 right = Some(
                     OpBuilder::insert(&insert.s[index..insert.num_chars()])
                         .attributes(attributes)
@@ -99,13 +93,9 @@ impl Operation {
                     OpBuilder::insert("").build()
                 } else {
                     let chars = insert.chars().skip(interval.start);
-                    let s = &chars
-                        .take(min(interval.size(), insert.num_chars()))
-                        .collect::<String>();
+                    let s = &chars.take(min(interval.size(), insert.num_chars())).collect::<String>();
 
-                    OpBuilder::insert(s)
-                        .attributes(insert.attributes.clone())
-                        .build()
+                    OpBuilder::insert(s).attributes(insert.attributes.clone()).build()
                 }
             },
         };
@@ -166,22 +156,12 @@ pub struct Retain {
 }
 
 impl fmt::Display for Retain {
-    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        f.write_fmt(format_args!(
-            "retain: {}, attributes: {}",
-            self.n, self.attributes
-        ))
-    }
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("retain: {}, attributes: {}", self.n, self.attributes)) }
 }
 
 impl Retain {
-    pub fn merge_or_new_op(&mut self, n: usize, attributes: Attributes) -> Option<Operation> {
-        log::debug!(
-            "merge_retain_or_new_op: len: {:?}, l: {} - r: {}",
-            n,
-            self.attributes,
-            attributes
-        );
+    pub fn merge_or_new(&mut self, n: usize, attributes: Attributes) -> Option<Operation> {
+        log::debug!("merge_retain_or_new_op: len: {:?}, l: {} - r: {}", n, self.attributes, attributes);
 
         if self.attributes == attributes {
             self.n += n;
@@ -232,10 +212,7 @@ impl fmt::Display for Insert {
             }
         }
 
-        f.write_fmt(format_args!(
-            "insert: {}, attributes: {}",
-            s, self.attributes
-        ))
+        f.write_fmt(format_args!("insert: {}, attributes: {}", s, self.attributes))
     }
 }
 

+ 3 - 14
rust-lib/flowy-ot/src/errors.rs

@@ -7,12 +7,7 @@ pub struct OTError {
 }
 
 impl OTError {
-    pub fn new(code: OTErrorCode, msg: &str) -> OTError {
-        Self {
-            code,
-            msg: msg.to_owned(),
-        }
-    }
+    pub fn new(code: OTErrorCode, msg: &str) -> OTError { Self { code, msg: msg.to_owned() } }
 }
 
 impl fmt::Display for OTError {
@@ -24,11 +19,7 @@ impl Error for OTError {
 }
 
 impl std::convert::From<serde_json::Error> for OTError {
-    fn from(error: serde_json::Error) -> Self {
-        ErrorBuilder::new(OTErrorCode::SerdeError)
-            .error(error)
-            .build()
-    }
+    fn from(error: serde_json::Error) -> Self { ErrorBuilder::new(OTErrorCode::SerdeError).error(error).build() }
 }
 
 #[derive(Debug, Clone)]
@@ -68,7 +59,5 @@ impl ErrorBuilder {
         self
     }
 
-    pub fn build(mut self) -> OTError {
-        OTError::new(self.code, &self.msg.take().unwrap_or("".to_owned()))
-    }
+    pub fn build(mut self) -> OTError { OTError::new(self.code, &self.msg.take().unwrap_or("".to_owned())) }
 }

+ 28 - 73
rust-lib/flowy-ot/tests/attribute_test.rs

@@ -39,10 +39,7 @@ fn attributes_bold_added_and_invert_partial_suffix() {
         Bold(0, Interval::new(0, 4), true),
         AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
         Bold(0, Interval::new(2, 4), false),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
     ];
     OpTester::new().run_script(ops);
 }
@@ -54,10 +51,7 @@ fn attributes_bold_added_and_invert_partial_suffix2() {
         Bold(0, Interval::new(0, 4), true),
         AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
         Bold(0, Interval::new(2, 4), false),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
         Bold(0, Interval::new(2, 4), true),
         AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
     ];
@@ -69,10 +63,7 @@ fn attributes_bold_added_with_new_line() {
     let ops = vec![
         Insert(0, "123456", 0),
         Bold(0, Interval::new(0, 6), true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
         Insert(0, "\n", 3),
         AssertOpsJson(
             0,
@@ -99,10 +90,7 @@ fn attributes_bold_added_and_invert_partial_prefix() {
         Bold(0, Interval::new(0, 4), true),
         AssertOpsJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#),
         Bold(0, Interval::new(0, 2), false),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#),
     ];
     OpTester::new().run_script(ops);
 }
@@ -112,15 +100,9 @@ fn attributes_bold_added_consecutive() {
     let ops = vec![
         Insert(0, "1234", 0),
         Bold(0, Interval::new(0, 1), true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"1","attributes":{"bold":"true"}},{"insert":"234"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"1","attributes":{"bold":"true"}},{"insert":"234"}]"#),
         Bold(0, Interval::new(1, 2), true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#),
     ];
     OpTester::new().run_script(ops);
 }
@@ -239,10 +221,7 @@ fn attributes_bold_added_italic_delete() {
             "#,
         ),
         Delete(0, Interval::new(0, 5)),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#),
     ];
 
     OpTester::new().run_script(ops);
@@ -387,10 +366,7 @@ fn attributes_replace_with_text() {
         InsertBold(0, "123456", Interval::new(0, 6)),
         AssertOpsJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#),
         Replace(0, Interval::new(0, 3), "ab"),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#),
     ];
 
     OpTester::new().run_script(ops);
@@ -400,11 +376,8 @@ fn attributes_replace_with_text() {
 fn attributes_header_insert_newline_at_middle() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":"1"}}]"#,
-        ),
+        Header(0, Interval::new(0, 6), 1),
+        AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":"1"}}]"#),
         Insert(0, "\n", 3),
         AssertOpsJson(
             0,
@@ -419,7 +392,7 @@ fn attributes_header_insert_newline_at_middle() {
 fn attributes_header_insert_double_newline_at_middle() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
+        Header(0, Interval::new(0, 6), 1),
         Insert(0, "\n", 3),
         AssertOpsJson(
             0,
@@ -444,7 +417,7 @@ fn attributes_header_insert_double_newline_at_middle() {
 fn attributes_header_insert_newline_at_trailing() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
+        Header(0, Interval::new(0, 6), 1),
         Insert(0, "\n", 6),
         AssertOpsJson(
             0,
@@ -459,7 +432,7 @@ fn attributes_header_insert_newline_at_trailing() {
 fn attributes_header_insert_double_newline_at_trailing() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
+        Header(0, Interval::new(0, 6), 1),
         Insert(0, "\n", 6),
         Insert(0, "\n", 7),
         AssertOpsJson(
@@ -475,7 +448,7 @@ fn attributes_header_insert_double_newline_at_trailing() {
 fn attributes_link_added() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Link(0, Interval::new(0, 6), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 6), "https://appflowy.io"),
         AssertOpsJson(
             0,
             r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
@@ -489,7 +462,7 @@ fn attributes_link_added() {
 fn attributes_link_format_with_bold() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Link(0, Interval::new(0, 6), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 6), "https://appflowy.io"),
         Bold(0, Interval::new(0, 3), true),
         AssertOpsJson(
             0,
@@ -508,7 +481,7 @@ fn attributes_link_format_with_bold() {
 fn attributes_link_insert_char_at_head() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Link(0, Interval::new(0, 6), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 6), "https://appflowy.io"),
         AssertOpsJson(
             0,
             r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
@@ -527,7 +500,7 @@ fn attributes_link_insert_char_at_head() {
 fn attributes_link_insert_char_at_middle() {
     let ops = vec![
         Insert(0, "1256", 0),
-        Link(0, Interval::new(0, 4), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 4), "https://appflowy.io"),
         Insert(0, "34", 2),
         AssertOpsJson(
             0,
@@ -542,7 +515,7 @@ fn attributes_link_insert_char_at_middle() {
 fn attributes_link_insert_char_at_trailing() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Link(0, Interval::new(0, 6), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 6), "https://appflowy.io"),
         AssertOpsJson(
             0,
             r#"[{"insert":"123456","attributes":{"link":"https://appflowy.io"}},{"insert":"\n"}]"#,
@@ -561,7 +534,7 @@ fn attributes_link_insert_char_at_trailing() {
 fn attributes_link_insert_newline_at_middle() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Link(0, Interval::new(0, 6), "https://appflowy.io", true),
+        Link(0, Interval::new(0, 6), "https://appflowy.io"),
         Insert(0, NEW_LINE, 3),
         AssertOpsJson(
             0,
@@ -593,7 +566,7 @@ fn attributes_link_auto_format_exist() {
     let site = "https://appflowy.io";
     let ops = vec![
         Insert(0, site, 0),
-        Link(0, Interval::new(0, site.len()), site, true),
+        Link(0, Interval::new(0, site.len()), site),
         Insert(0, WHITESPACE, site.len()),
         AssertOpsJson(
             0,
@@ -609,7 +582,7 @@ fn attributes_link_auto_format_exist2() {
     let site = "https://appflowy.io";
     let ops = vec![
         Insert(0, site, 0),
-        Link(0, Interval::new(0, site.len() / 2), site, true),
+        Link(0, Interval::new(0, site.len() / 2), site),
         Insert(0, WHITESPACE, site.len()),
         AssertOpsJson(
             0,
@@ -625,10 +598,7 @@ fn attributes_bullet_added() {
     let ops = vec![
         Insert(0, "12", 0),
         Bullet(0, Interval::new(0, 1), true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"\n","attributes":{"bullet":"true"}}]"#),
     ];
 
     OpTester::new().run_script_with_newline(ops);
@@ -639,15 +609,9 @@ fn attributes_bullet_added_2() {
     let ops = vec![
         Insert(0, "1", 0),
         Bullet(0, Interval::new(0, 1), true),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}}]"#),
         Insert(0, NEW_LINE, 1),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"1"},{"insert":"\n\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n\n","attributes":{"bullet":"true"}}]"#),
         Insert(0, "2", 2),
         AssertOpsJson(
             0,
@@ -697,10 +661,7 @@ fn attributes_preserve_block_when_insert_newline_inside() {
         Insert(0, "12", 0),
         Bullet(0, Interval::new(0, 2), true),
         Insert(0, NEW_LINE, 2),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"12"},{"insert":"\n\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"12"},{"insert":"\n\n","attributes":{"bullet":"true"}}]"#),
         Insert(0, "34", 3),
         AssertOpsJson(
             0,
@@ -735,17 +696,14 @@ fn attributes_preserve_block_when_insert_newline_inside() {
 fn attributes_preserve_header_format_on_merge() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
+        Header(0, Interval::new(0, 6), 1),
         Insert(0, NEW_LINE, 3),
         AssertOpsJson(
             0,
             r#"[{"insert":"123"},{"insert":"\n","attributes":{"header":"1"}},{"insert":"456"},{"insert":"\n","attributes":{"header":"1"}}]"#,
         ),
         Delete(0, Interval::new(3, 4)),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":"1"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":"1"}}]"#),
     ];
 
     OpTester::new().run_script_with_newline(ops);
@@ -762,10 +720,7 @@ fn attributes_preserve_list_format_on_merge() {
             r#"[{"insert":"123"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
         ),
         Delete(0, Interval::new(3, 4)),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#),
     ];
 
     OpTester::new().run_script_with_newline(ops);

+ 13 - 32
rust-lib/flowy-ot/tests/helper/mod.rs

@@ -28,10 +28,10 @@ pub enum TestOp {
     Italic(usize, Interval, bool),
 
     #[display(fmt = "Header")]
-    Header(usize, Interval, usize, bool),
+    Header(usize, Interval, usize),
 
     #[display(fmt = "Link")]
-    Link(usize, Interval, &'static str, bool),
+    Link(usize, Interval, &'static str),
 
     #[display(fmt = "Bullet")]
     Bullet(usize, Interval, bool),
@@ -93,48 +93,34 @@ impl OpTester {
             TestOp::InsertBold(delta_i, s, iv) => {
                 let document = &mut self.documents[*delta_i];
                 document.insert(iv.start, s).unwrap();
-                document
-                    .format(*iv, AttributeKey::Bold.value(true))
-                    .unwrap();
+                document.format(*iv, Attribute::Bold(true)).unwrap();
             },
             TestOp::Bold(delta_i, iv, enable) => {
                 let document = &mut self.documents[*delta_i];
-                let attribute = match *enable {
-                    true => AttributeKey::Bold.value(true),
-                    false => AttributeKey::Bold.remove(),
-                };
+                let attribute = Attribute::Bold(*enable);
                 document.format(*iv, attribute).unwrap();
             },
             TestOp::Italic(delta_i, iv, enable) => {
                 let document = &mut self.documents[*delta_i];
                 let attribute = match *enable {
-                    true => AttributeKey::Italic.value("true"),
-                    false => AttributeKey::Italic.remove(),
+                    true => Attribute::Italic(true),
+                    false => Attribute::Italic(false),
                 };
                 document.format(*iv, attribute).unwrap();
             },
-            TestOp::Header(delta_i, iv, level, enable) => {
+            TestOp::Header(delta_i, iv, level) => {
                 let document = &mut self.documents[*delta_i];
-                let attribute = match *enable {
-                    true => AttributeKey::Header.value(level),
-                    false => AttributeKey::Header.remove(),
-                };
+                let attribute = Attribute::Header(*level);
                 document.format(*iv, attribute).unwrap();
             },
-            TestOp::Link(delta_i, iv, link, enable) => {
+            TestOp::Link(delta_i, iv, link) => {
                 let document = &mut self.documents[*delta_i];
-                let attribute = match *enable {
-                    true => AttributeKey::Link.value(link.to_owned()),
-                    false => AttributeKey::Link.remove(),
-                };
+                let attribute = Attribute::Link(link.to_owned());
                 document.format(*iv, attribute).unwrap();
             },
             TestOp::Bullet(delta_i, iv, enable) => {
                 let document = &mut self.documents[*delta_i];
-                let attribute = match *enable {
-                    true => AttributeKey::Bullet.value("true"),
-                    false => AttributeKey::Bullet.remove(),
-                };
+                let attribute = Attribute::Bullet(*enable);
                 document.format(*iv, attribute).unwrap();
             },
             TestOp::Transform(delta_a_i, delta_b_i) => {
@@ -236,9 +222,7 @@ impl Default for Rng {
 impl Rng {
     pub fn from_seed(seed: [u8; 32]) -> Self { Rng(StdRng::from_seed(seed)) }
 
-    pub fn gen_string(&mut self, len: usize) -> String {
-        (0..len).map(|_| self.0.gen::<char>()).collect()
-    }
+    pub fn gen_string(&mut self, len: usize) -> String { (0..len).map(|_| self.0.gen::<char>()).collect() }
 
     pub fn gen_delta(&mut self, s: &str) -> Delta {
         let mut delta = Delta::default();
@@ -265,10 +249,7 @@ impl Rng {
             }
         }
         if self.0.gen_range(0.0, 1.0) < 0.3 {
-            delta.insert(
-                &("1".to_owned() + &self.gen_string(10)),
-                Attributes::default(),
-            );
+            delta.insert(&("1".to_owned() + &self.gen_string(10)), Attributes::default());
         }
         delta
     }

+ 23 - 71
rust-lib/flowy-ot/tests/op_test.rs

@@ -71,10 +71,7 @@ fn delta_get_ops_in_interval_2() {
         vec![OpBuilder::insert("23").build()]
     );
 
-    assert_eq!(
-        DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(),
-        vec![insert_a.clone()]
-    );
+    assert_eq!(DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(), vec![insert_a.clone()]);
 
     assert_eq!(
         DeltaIter::from_interval(&delta, Interval::new(0, 4)).ops(),
@@ -114,25 +111,13 @@ fn delta_get_ops_in_interval_4() {
     delta.ops.push(insert_b.clone());
     delta.ops.push(insert_c.clone());
 
-    assert_eq!(
-        DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(),
-        vec![insert_a]
-    );
-    assert_eq!(
-        DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(),
-        vec![insert_b]
-    );
-    assert_eq!(
-        DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(),
-        vec![insert_c]
-    );
+    assert_eq!(DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(), vec![insert_a]);
+    assert_eq!(DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(), vec![insert_b]);
+    assert_eq!(DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(), vec![insert_c]);
 
     assert_eq!(
         DeltaIter::from_interval(&delta, Interval::new(2, 5)).ops(),
-        vec![
-            OpBuilder::insert("34").build(),
-            OpBuilder::insert("5").build()
-        ]
+        vec![OpBuilder::insert("34").build(), OpBuilder::insert("5").build()]
     );
 }
 
@@ -145,10 +130,7 @@ fn delta_get_ops_in_interval_5() {
     delta.ops.push(insert_b.clone());
     assert_eq!(
         DeltaIter::from_interval(&delta, Interval::new(4, 8)).ops(),
-        vec![
-            OpBuilder::insert("56").build(),
-            OpBuilder::insert("78").build()
-        ]
+        vec![OpBuilder::insert("56").build(), OpBuilder::insert("78").build()]
     );
 
     // assert_eq!(
@@ -182,10 +164,7 @@ fn delta_get_ops_in_interval_7() {
     assert_eq!(iter_1.next_op().unwrap(), OpBuilder::retain(3).build());
 
     let mut iter_2 = DeltaIter::new(&delta);
-    assert_eq!(
-        iter_2.next_op_with_len(2).unwrap(),
-        OpBuilder::insert("12").build()
-    );
+    assert_eq!(iter_2.next_op_with_len(2).unwrap(), OpBuilder::insert("12").build());
     assert_eq!(iter_2.next_op().unwrap(), OpBuilder::insert("345").build());
 
     assert_eq!(iter_2.next_op().unwrap(), OpBuilder::retain(3).build());
@@ -209,10 +188,7 @@ fn delta_seek_2() {
     delta.add(OpBuilder::insert("12345").build());
 
     let mut iter = DeltaIter::new(&delta);
-    assert_eq!(
-        iter.next_op_with_len(1).unwrap(),
-        OpBuilder::insert("1").build()
-    );
+    assert_eq!(iter.next_op_with_len(1).unwrap(), OpBuilder::insert("1").build());
 }
 
 #[test]
@@ -221,20 +197,11 @@ fn delta_seek_3() {
     delta.add(OpBuilder::insert("12345").build());
 
     let mut iter = DeltaIter::new(&delta);
-    assert_eq!(
-        iter.next_op_with_len(2).unwrap(),
-        OpBuilder::insert("12").build()
-    );
+    assert_eq!(iter.next_op_with_len(2).unwrap(), OpBuilder::insert("12").build());
 
-    assert_eq!(
-        iter.next_op_with_len(2).unwrap(),
-        OpBuilder::insert("34").build()
-    );
+    assert_eq!(iter.next_op_with_len(2).unwrap(), OpBuilder::insert("34").build());
 
-    assert_eq!(
-        iter.next_op_with_len(2).unwrap(),
-        OpBuilder::insert("5").build()
-    );
+    assert_eq!(iter.next_op_with_len(2).unwrap(), OpBuilder::insert("5").build());
 
     assert_eq!(iter.next_op_with_len(1), None);
 }
@@ -246,21 +213,18 @@ fn delta_seek_4() {
 
     let mut iter = DeltaIter::new(&delta);
     iter.seek::<CharMetric>(3);
-    assert_eq!(
-        iter.next_op_with_len(2).unwrap(),
-        OpBuilder::insert("45").build()
-    );
+    assert_eq!(iter.next_op_with_len(2).unwrap(), OpBuilder::insert("45").build());
 }
 
 #[test]
 fn delta_seek_5() {
     let mut delta = Delta::default();
-    let attributes = AttributeBuilder::new().bold(true).italic(true).build();
-    delta.add(
-        OpBuilder::insert("1234")
-            .attributes(attributes.clone())
-            .build(),
-    );
+    let attributes = AttributeBuilder::new()
+        .add(Attribute::Bold(true))
+        .add(Attribute::Italic(true))
+        .build();
+
+    delta.add(OpBuilder::insert("1234").attributes(attributes.clone()).build());
     delta.add(OpBuilder::insert("\n").build());
 
     let mut iter = DeltaIter::new(&delta);
@@ -280,10 +244,7 @@ fn delta_next_op_len_test() {
     let mut iter = DeltaIter::new(&delta);
     iter.seek::<CharMetric>(3);
     assert_eq!(iter.next_op_len().unwrap(), 2);
-    assert_eq!(
-        iter.next_op_with_len(1).unwrap(),
-        OpBuilder::insert("4").build()
-    );
+    assert_eq!(iter.next_op_with_len(1).unwrap(), OpBuilder::insert("4").build());
     assert_eq!(iter.next_op_len().unwrap(), 1);
     assert_eq!(iter.next_op().unwrap(), OpBuilder::insert("5").build());
 }
@@ -295,10 +256,7 @@ fn delta_next_op_len_test2() {
     let mut iter = DeltaIter::new(&delta);
 
     assert_eq!(iter.next_op_len().unwrap(), 5);
-    assert_eq!(
-        iter.next_op_with_len(5).unwrap(),
-        OpBuilder::insert("12345").build()
-    );
+    assert_eq!(iter.next_op_with_len(5).unwrap(), OpBuilder::insert("12345").build());
     assert_eq!(iter.next_op_len(), None);
 }
 
@@ -321,10 +279,7 @@ fn delta_next_op_with_len_cross_op_return_last() {
     let mut iter = DeltaIter::new(&delta);
     iter.seek::<CharMetric>(4);
     assert_eq!(iter.next_op_len().unwrap(), 1);
-    assert_eq!(
-        iter.next_op_with_len(2).unwrap(),
-        OpBuilder::retain(1).build()
-    );
+    assert_eq!(iter.next_op_with_len(2).unwrap(), OpBuilder::retain(1).build());
 }
 
 #[test]
@@ -523,7 +478,7 @@ fn transform2() {
 fn delta_transform_test() {
     let mut a = Delta::default();
     let mut a_s = String::new();
-    a.insert("123", AttributeBuilder::new().bold(true).build());
+    a.insert("123", AttributeBuilder::new().add(Attribute::Bold(true)).build());
     a_s = a.apply(&a_s).unwrap();
     assert_eq!(&a_s, "123");
 
@@ -625,10 +580,7 @@ fn delta_invert_no_attribute_delta_with_attribute_delta() {
         Insert(0, "123", 0),
         Insert(1, "4567", 0),
         Bold(1, Interval::new(0, 3), true),
-        AssertOpsJson(
-            1,
-            r#"[{"insert":"456","attributes":{"bold":"true"}},{"insert":"7"}]"#,
-        ),
+        AssertOpsJson(1, r#"[{"insert":"456","attributes":{"bold":"true"}},{"insert":"7"}]"#),
         Invert(0, 1),
         AssertOpsJson(0, r#"[{"insert":"123"}]"#),
     ];

+ 8 - 2
rust-lib/flowy-ot/tests/serde_test.rs

@@ -2,7 +2,10 @@ use flowy_ot::{client::Document, core::*};
 
 #[test]
 fn operation_insert_serialize_test() {
-    let attributes = AttributeBuilder::new().bold(true).italic(true).build();
+    let attributes = AttributeBuilder::new()
+        .add(Attribute::Bold(true))
+        .add(Attribute::Italic(true))
+        .build();
     let operation = OpBuilder::insert("123").attributes(attributes).build();
     let json = serde_json::to_string(&operation).unwrap();
     eprintln!("{}", json);
@@ -32,7 +35,10 @@ fn operation_delete_serialize_test() {
 fn delta_serialize_test() {
     let mut delta = Delta::default();
 
-    let attributes = AttributeBuilder::new().bold(true).italic(true).build();
+    let attributes = AttributeBuilder::new()
+        .add(Attribute::Bold(true))
+        .add(Attribute::Italic(true))
+        .build();
     let retain = OpBuilder::insert("123").attributes(attributes).build();
 
     delta.add(retain);

+ 8 - 27
rust-lib/flowy-ot/tests/undo_redo_test.rs

@@ -8,11 +8,7 @@ use flowy_ot::{
 
 #[test]
 fn history_insert_undo() {
-    let ops = vec![
-        Insert(0, "123", 0),
-        Undo(0),
-        AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
-    ];
+    let ops = vec![Insert(0, "123", 0), Undo(0), AssertOpsJson(0, r#"[{"insert":"\n"}]"#)];
     OpTester::new().run_script_with_newline(ops);
 }
 
@@ -93,10 +89,7 @@ fn history_bold_redo() {
         Undo(0),
         AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
         Redo(0),
-        AssertOpsJson(
-            0,
-            r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
-        ),
+        AssertOpsJson(0, r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
     ];
     OpTester::new().run_script_with_newline(ops);
 }
@@ -110,10 +103,7 @@ fn history_bold_redo_with_lagging() {
         Undo(0),
         AssertOpsJson(0, r#"[{"insert":"123\n"}]"#),
         Redo(0),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
     ];
     OpTester::new().run_script_with_newline(ops);
 }
@@ -226,10 +216,7 @@ fn history_replace_undo_with_lagging() {
             "#,
         ),
         Undo(0),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#),
     ];
     OpTester::new().run_script_with_newline(ops);
 }
@@ -257,7 +244,7 @@ fn history_replace_redo() {
 fn history_header_added_undo() {
     let ops = vec![
         Insert(0, "123456", 0),
-        Header(0, Interval::new(0, 6), 1, true),
+        Header(0, Interval::new(0, 6), 1),
         Insert(0, "\n", 3),
         Insert(0, "\n", 4),
         Undo(0),
@@ -278,7 +265,7 @@ fn history_link_added_undo() {
     let ops = vec![
         Insert(0, site, 0),
         Wait(RECORD_THRESHOLD),
-        Link(0, Interval::new(0, site.len()), site, true),
+        Link(0, Interval::new(0, site.len()), site),
         Undo(0),
         AssertOpsJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#),
         Redo(0),
@@ -347,10 +334,7 @@ fn history_bullet_undo_with_lagging() {
             r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"2"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
         ),
         Undo(0),
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"1"},{"insert":"\n","attributes":{"bullet":"true"}}]"#),
         Undo(0),
         AssertOpsJson(0, r#"[{"insert":"\n"}]"#),
         Redo(0),
@@ -377,10 +361,7 @@ fn history_undo_attribute_on_merge_between_line() {
             r#"[{"insert":"123"},{"insert":"\n","attributes":{"bullet":"true"}},{"insert":"456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
         ),
         Delete(0, Interval::new(3, 4)), // delete the newline
-        AssertOpsJson(
-            0,
-            r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#,
-        ),
+        AssertOpsJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"bullet":"true"}}]"#),
         Undo(0),
         AssertOpsJson(
             0,

+ 2 - 11
rust-lib/flowy-sqlite/src/conn_ext.rs

@@ -1,12 +1,5 @@
 use crate::errors::*;
-use diesel::{
-    dsl::sql,
-    expression::SqlLiteral,
-    query_dsl::LoadQuery,
-    Connection,
-    RunQueryDsl,
-    SqliteConnection,
-};
+use diesel::{dsl::sql, expression::SqlLiteral, query_dsl::LoadQuery, Connection, RunQueryDsl, SqliteConnection};
 
 pub trait ConnectionExtension: Connection {
     fn query<ST, T>(&self, query: &str) -> Result<T>
@@ -24,7 +17,5 @@ impl ConnectionExtension for SqliteConnection {
         Ok(sql::<ST>(query).get_result(self)?)
     }
 
-    fn exec(&self, query: impl AsRef<str>) -> Result<usize> {
-        Ok(SqliteConnection::execute(self, query.as_ref())?)
-    }
+    fn exec(&self, query: impl AsRef<str>) -> Result<usize> { Ok(SqliteConnection::execute(self, query.as_ref())?) }
 }

+ 1 - 4
rust-lib/flowy-sqlite/src/database.rs

@@ -21,10 +21,7 @@ impl Database {
         }
 
         let pool = ConnectionPool::new(pool_config, &uri)?;
-        Ok(Self {
-            uri,
-            pool: Arc::new(pool),
-        })
+        Ok(Self { uri, pool: Arc::new(pool) })
     }
 
     pub fn get_uri(&self) -> &str { &self.uri }

+ 1 - 7
rust-lib/flowy-sqlite/src/errors.rs

@@ -1,10 +1,4 @@
-use error_chain::{
-    error_chain,
-    error_chain_processing,
-    impl_error_chain_kind,
-    impl_error_chain_processed,
-    impl_extract_backtrace,
-};
+use error_chain::{error_chain, error_chain_processing, impl_error_chain_kind, impl_error_chain_processed, impl_extract_backtrace};
 
 error_chain! {
     errors {

+ 1 - 3
rust-lib/flowy-sqlite/src/pool.rs

@@ -119,9 +119,7 @@ impl ManageConnection for ConnectionManager {
 
     fn connect(&self) -> Result<Self::Connection> { Ok(SqliteConnection::establish(&self.db_uri)?) }
 
-    fn is_valid(&self, conn: &mut Self::Connection) -> Result<()> {
-        Ok(conn.execute("SELECT 1").map(|_| ())?)
-    }
+    fn is_valid(&self, conn: &mut Self::Connection) -> Result<()> { Ok(conn.execute("SELECT 1").map(|_| ())?) }
 
     fn has_broken(&self, _conn: &mut Self::Connection) -> bool { false }
 }

+ 6 - 25
rust-lib/flowy-sqlite/src/pragma.rs

@@ -24,12 +24,7 @@ pub trait PragmaExtension: ConnectionExtension {
         Ok(())
     }
 
-    fn pragma_ret<ST, T, D: std::fmt::Display>(
-        &self,
-        key: &str,
-        val: D,
-        schema: Option<&str>,
-    ) -> Result<T>
+    fn pragma_ret<ST, T, D: std::fmt::Display>(&self, key: &str, val: D, schema: Option<&str>) -> Result<T>
     where
         SqlLiteral<ST>: LoadQuery<SqliteConnection, T>,
     {
@@ -57,36 +52,22 @@ pub trait PragmaExtension: ConnectionExtension {
         self.pragma_ret::<Integer, i32, i32>("busy_timeout", timeout_ms, None)
     }
 
-    fn pragma_get_busy_timeout(&self) -> Result<i32> {
-        self.pragma_get::<Integer, i32>("busy_timeout", None)
-    }
+    fn pragma_get_busy_timeout(&self) -> Result<i32> { self.pragma_get::<Integer, i32>("busy_timeout", None) }
 
-    fn pragma_set_journal_mode(
-        &self,
-        mode: SQLiteJournalMode,
-        schema: Option<&str>,
-    ) -> Result<i32> {
+    fn pragma_set_journal_mode(&self, mode: SQLiteJournalMode, schema: Option<&str>) -> Result<i32> {
         self.pragma_ret::<Integer, i32, SQLiteJournalMode>("journal_mode", mode, schema)
     }
 
     fn pragma_get_journal_mode(&self, schema: Option<&str>) -> Result<SQLiteJournalMode> {
-        Ok(self
-            .pragma_get::<Text, String>("journal_mode", schema)?
-            .parse()?)
+        Ok(self.pragma_get::<Text, String>("journal_mode", schema)?.parse()?)
     }
 
-    fn pragma_set_synchronous(
-        &self,
-        synchronous: SQLiteSynchronous,
-        schema: Option<&str>,
-    ) -> Result<()> {
+    fn pragma_set_synchronous(&self, synchronous: SQLiteSynchronous, schema: Option<&str>) -> Result<()> {
         self.pragma("synchronous", synchronous as u8, schema)
     }
 
     fn pragma_get_synchronous(&self, schema: Option<&str>) -> Result<SQLiteSynchronous> {
-        Ok(self
-            .pragma_get::<Integer, i32>("synchronous", schema)?
-            .try_into()?)
+        Ok(self.pragma_get::<Integer, i32>("synchronous", schema)?.try_into()?)
     }
 }
 impl PragmaExtension for SqliteConnection {}

+ 1 - 3
rust-lib/flowy-user/src/entities/parser/user_email.rs

@@ -57,7 +57,5 @@ mod tests {
     }
 
     #[quickcheck_macros::quickcheck]
-    fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool {
-        UserEmail::parse(valid_email.0).is_ok()
-    }
+    fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool { UserEmail::parse(valid_email.0).is_ok() }
 }

+ 1 - 4
rust-lib/flowy-user/src/errors.rs

@@ -3,10 +3,7 @@ use derive_more::Display;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_dispatch::prelude::{EventResponse, ResponseBuilder};
 
-use std::{
-    convert::TryInto,
-    fmt::{Debug, Formatter},
-};
+use std::{convert::TryInto, fmt::Debug};
 
 #[derive(Debug, Default, Clone, ProtoBuf)]
 pub struct UserError {

+ 0 - 2
rust-lib/flowy-user/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 13 - 13
rust-lib/flowy-user/src/protobuf/model/mod.rs

@@ -1,19 +1,19 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod user_table; 
-pub use user_table::*; 
+mod user_table;
+pub use user_table::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod user_profile; 
-pub use user_profile::*; 
+mod user_profile;
+pub use user_profile::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod auth; 
-pub use auth::*; 
+mod auth;
+pub use auth::*;

+ 1 - 5
rust-lib/flowy-workspace/src/entities/workspace/workspace_delete.rs

@@ -22,11 +22,7 @@ impl TryInto<DeleteWorkspaceParams> for DeleteWorkspaceRequest {
 
     fn try_into(self) -> Result<DeleteWorkspaceParams, Self::Error> {
         let workspace_id = WorkspaceId::parse(self.workspace_id)
-            .map_err(|e| {
-                ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid)
-                    .msg(e)
-                    .build()
-            })?
+            .map_err(|e| ErrorBuilder::new(ErrorCode::WorkspaceIdInvalid).msg(e).build())?
             .0;
 
         Ok(DeleteWorkspaceParams { workspace_id })

+ 9 - 10
rust-lib/flowy-workspace/src/handlers/view_handler.rs

@@ -54,6 +54,15 @@ pub(crate) async fn update_view_handler(
 
     Ok(())
 }
+#[tracing::instrument(skip(data, controller), err)]
+pub(crate) async fn update_view_data_handler(
+    data: Data<UpdateViewDataRequest>,
+    controller: Unit<Arc<ViewController>>,
+) -> Result<(), WorkspaceError> {
+    let params: UpdateDocParams = data.into_inner().try_into()?;
+    let _ = controller.update_view_data(params).await?;
+    Ok(())
+}
 
 #[tracing::instrument(skip(data, controller), err)]
 pub(crate) async fn delete_view_handler(
@@ -74,13 +83,3 @@ pub(crate) async fn open_view_handler(
     let doc = controller.open_view(params).await?;
     data_result(doc)
 }
-
-#[tracing::instrument(skip(data, controller), err)]
-pub(crate) async fn update_view_data_handler(
-    data: Data<UpdateViewDataRequest>,
-    controller: Unit<Arc<ViewController>>,
-) -> Result<(), WorkspaceError> {
-    let params: UpdateDocParams = data.into_inner().try_into()?;
-    let _ = controller.update_view_data(params).await?;
-    Ok(())
-}

+ 6 - 19
rust-lib/flowy-workspace/src/macros.rs

@@ -1,15 +1,13 @@
 #[macro_export]
 macro_rules! impl_sql_binary_expression {
     ($target:ident) => {
-        impl diesel::serialize::ToSql<diesel::sql_types::Binary, diesel::sqlite::Sqlite>
-            for $target
-        {
+        impl diesel::serialize::ToSql<diesel::sql_types::Binary, diesel::sqlite::Sqlite> for $target {
             fn to_sql<W: std::io::Write>(
                 &self,
                 out: &mut diesel::serialize::Output<W, diesel::sqlite::Sqlite>,
             ) -> diesel::serialize::Result {
                 let bytes: Vec<u8> = self.try_into().map_err(|e| format!("{:?}", e))?;
-                diesel::serialize::ToSql::<diesel::sql_types::Binary,diesel::sqlite::Sqlite,>::to_sql(&bytes, out)
+                diesel::serialize::ToSql::<diesel::sql_types::Binary, diesel::sqlite::Sqlite>::to_sql(&bytes, out)
             }
         }
         // https://docs.diesel.rs/src/diesel/sqlite/types/mod.rs.html#30-33
@@ -25,20 +23,13 @@ macro_rules! impl_sql_binary_expression {
             *const [u8]: diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>,
         {
             fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
-                let slice_ptr = <*const [u8] as diesel::deserialize::FromSql<
-                    diesel::sql_types::Binary,
-                    DB,
-                >>::from_sql(bytes)?;
+                let slice_ptr = <*const [u8] as diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>>::from_sql(bytes)?;
                 let bytes = unsafe { &*slice_ptr };
 
                 match $target::try_from(bytes) {
                     Ok(object) => Ok(object),
                     Err(e) => {
-                        log::error!(
-                            "{:?} deserialize from bytes fail. {:?}",
-                            std::any::type_name::<$target>(),
-                            e
-                        );
+                        log::error!("{:?} deserialize from bytes fail. {:?}", std::any::type_name::<$target>(), e);
                         panic!();
                     },
                 }
@@ -63,9 +54,7 @@ macro_rules! impl_sql_integer_expression {
             DB: diesel::backend::Backend,
             i32: ToSql<Integer, DB>,
         {
-            fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
-                (*self as i32).to_sql(out)
-            }
+            fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result { (*self as i32).to_sql(out) }
         }
 
         impl<DB> FromSql<Integer, DB> for $target
@@ -105,9 +94,7 @@ macro_rules! impl_def_and_def_mut {
 
         impl $target {
             #[allow(dead_code)]
-            pub fn take_items(&mut self) -> Vec<$item> {
-                ::std::mem::replace(&mut self.items, vec![])
-            }
+            pub fn take_items(&mut self) -> Vec<$item> { ::std::mem::replace(&mut self.items, vec![]) }
 
             #[allow(dead_code)]
             pub fn push(&mut self, item: $item) {

+ 0 - 2
rust-lib/flowy-workspace/src/protobuf/mod.rs

@@ -1,4 +1,2 @@
-
 mod model;
 pub use model::*;
-        

+ 33 - 33
rust-lib/flowy-workspace/src/protobuf/model/mod.rs

@@ -1,49 +1,49 @@
-// Auto-generated, do not edit 
+// Auto-generated, do not edit
 
-mod view_update; 
-pub use view_update::*; 
+mod view_update;
+pub use view_update::*;
 
-mod view_delete; 
-pub use view_delete::*; 
+mod view_delete;
+pub use view_delete::*;
 
-mod app_query; 
-pub use app_query::*; 
+mod app_query;
+pub use app_query::*;
 
-mod workspace_delete; 
-pub use workspace_delete::*; 
+mod workspace_delete;
+pub use workspace_delete::*;
 
-mod observable; 
-pub use observable::*; 
+mod observable;
+pub use observable::*;
 
-mod errors; 
-pub use errors::*; 
+mod errors;
+pub use errors::*;
 
-mod workspace_update; 
-pub use workspace_update::*; 
+mod workspace_update;
+pub use workspace_update::*;
 
-mod app_create; 
-pub use app_create::*; 
+mod app_create;
+pub use app_create::*;
 
-mod workspace_query; 
-pub use workspace_query::*; 
+mod workspace_query;
+pub use workspace_query::*;
 
-mod event; 
-pub use event::*; 
+mod event;
+pub use event::*;
 
-mod view_create; 
-pub use view_create::*; 
+mod view_create;
+pub use view_create::*;
 
-mod workspace_user_detail; 
-pub use workspace_user_detail::*; 
+mod workspace_user_detail;
+pub use workspace_user_detail::*;
 
-mod workspace_create; 
-pub use workspace_create::*; 
+mod workspace_create;
+pub use workspace_create::*;
 
-mod app_update; 
-pub use app_update::*; 
+mod app_update;
+pub use app_update::*;
 
-mod view_query; 
-pub use view_query::*; 
+mod view_query;
+pub use view_query::*;
 
-mod app_delete; 
-pub use app_delete::*; 
+mod app_delete;
+pub use app_delete::*;

+ 1 - 1
rust-lib/flowy-workspace/src/services/app_controller.rs

@@ -149,7 +149,7 @@ impl AppController {
             match server.read_app(&token, params).await {
                 Ok(option) => match option {
                     None => {},
-                    Some(app) => {},
+                    Some(_app) => {},
                 },
                 Err(_) => {},
             }

+ 1 - 1
rust-lib/flowy-workspace/tests/workspace/helper.rs

@@ -114,7 +114,7 @@ pub fn read_workspace(sdk: &FlowyTestSDK, request: QueryWorkspaceRequest) -> Opt
         .sync_send()
         .parse::<RepeatedWorkspace>();
 
-    let mut workspaces = vec![];
+    let mut workspaces;
     if let Some(workspace_id) = &request.workspace_id {
         workspaces = repeated_workspace
             .take_items()