%% BibBreeze.bbx

% Author: Amir Mohammad Tahsiri
% contact: https://github.com/mamadgit/BibBreeze

%% Copyright 2025 Amir Mohammad Tahsiri
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Amir Mohammad Tahsiri.
%
% This work consists of the files BibBreeze.tex, BibBreeze.bbx, BibBreeze-authoryear.cbx, BibBreeze.dbx, BibBreeze.bib, BibBreeze.def, Instructions-Descriptions.md, README.md and the derived file LICENSE.txt.

\ProvidesFile{BibBreeze.bbx}[version 1.1] 
\RequireBibliographyStyle{numeric}% If users want there references based on author-year, change "numeric" to "BibBreeze-authoryear".

\DeclareSortingTemplate{nyt}
{%  
  \sort{  
    \field{presort}  
  }
  \sort{  
    \field{sortname}  
    \field{author}  
    \field{editor}  
    \field{translator}  
    \field{sorttitle}  
    \field{title}  
  }   
  \sort[final]{  
    \field{sortyear}  
    \field{year}  
    \field{month}  
    \field{day}  
    \field{sorttitle} 
    \field{title}  
  }   
}  
% Multi-letter label alphabet for year disambiguation  
\DeclareLabelalphaTemplate
{  
  \labelelement{  
    \field[strwidth=1,strside=left,ifnames=1]{labelname}  
    \field[strwidth=1,strside=left,ifnames=1]{author}  
    \field[strwidth=1,strside=left,ifnames=1]{editor}  
  }  
  \labelelement{  
    \field[strwidth=1,strside=right]{labelname}  
    \field[strwidth=1,strside=right]{author}  
    \field[strwidth=1,strside=right]{editor}  
  }  
  \labelelement{  
    \field[strwidth=2]{year}  
  }  
}  

%The format of how authors should be printed across all types of entries
\DeclareNameFormat{author}
{%  
  \nameparts{#1}%  
  \ifblank{\namepartfamily}  
    {}  
    {\namepartfamily\addcomma\space}%  Add Authors surname
  \ifblank{\namepartgiven}  
    {}  
    {\namepartgiveni\adddot}%  Add authors intial first name
    \ifthenelse{\value{listcount}<\value{liststop}}% Not the last author  
    {\ifthenelse{\value{listcount}=\numexpr\value{liststop}-1\relax}% Second to last author  
      {\addcomma\addspace\&} % Add '&' before the last author's name  
      } % Add comma after other authors  
    {} % Do not add anything after the last author    
    {\ifthenelse{\value{listcount}<20 \OR (\value{listcount}=20 \AND \value{liststop}>21)}  
      {\addcomma\space} % Add commas for the first 19 authors or if there are more than 21 authors, add comma before ellipsis  
      {\ifthenelse{\value{listcount}=20 \AND \value{liststop}>21}  
        {\addspace...\space} % After the 19th author, add ellipsis for more than 21 authors  
          {\ifthenelse{\value{listcount}=21}  
            {\addcomma\space\namepartfamily\addcomma\space\namepartgiveni\adddot} % Add final author's name after ellipsis for more than 21 authors  
            {}}}}  
          % Add comma and space after each author's name
}   

%The format of how authors should be printed across all types of entries
\DeclareNameFormat{editor}
{%
  \nameparts{#1}%
  \ifblank{\namepartgiven}
  {}
  {\namepartgiveni\adddot\space}% Add Editors intial first name
  \ifblank{\namepartfamily}
    {}
    {\namepartfamily\space}% Add Editors surname
    \ifthenelse{\value{listcount}<\value{liststop}}% Not the last editor
    {\ifthenelse{\value{listcount}=\numexpr\value{liststop}-1\relax}% Second to last editor
      {\addspace\&\space} % Add '&' before the last author's name
      {\addspace}}% Add comma after other authors
    {}% If only one editor, do nothing here
} 

% Format the DOI to print the URL without "doi:" and handle existing http(s) links correctly
% Define the format for the DOI field in BibLaTeX
\DeclareFieldFormat{doi}
{
  % Check if the DOI field is undefined in the bibliography entry
  \iffieldundef{doi}{%
    % If the DOI field is empty, do nothing (leave the field blank)
  }{%
    % Check if the DOI field is explicitly empty
    \ifx#1\empty%
    \else
      % Check if the DOI field is set to \relax, which is another way to indicate an empty field
      \ifx#1\relax
      \else
        % Extract the first five characters of the DOI to determine its prefix
        \StrLeft{#1}{5}[\prefix]%
        % Use \expandafter to ensure macro expansion before comparison
        \expandafter\ifstrequal\expandafter{\prefix}{https}{% If the DOI starts with "https", print as is
          \href{#1}{\nolinkurl{#1}}%Format the URL text to make to preseve line break
        }{%
          \expandafter\ifstrequal\expandafter{\prefix}{http:}{%
            % If the DOI starts with "http", print as is
            \href{#1}{\nolinkurl{#1}}%
          }{%
            %Prepend "https://doi.org/" to the DOI and format it as a hyperlink
            \href{https://doi.org/#1}{\nolinkurl{https://doi.org/#1}}%
          }%
        }%
      \fi
    \fi
  }%
}
% Universal URL format without the "URL" label
\DeclareFieldFormat{url}{%
  \ifhyperref
    {\href{#1}{\nolinkurl{#1}}}
    {\nolinkurl{#1}}%
}
\DeclareFieldFormat[article]{title}{#1}   
\DeclareFieldFormat[article]{year}
{% Enable 'extrayear' field for distinguishing entries with the same year  
  (#1%  
  \iffieldundef{extrayear}  
    {}  
    {\printfield{extrayear}}%  
  )
}

\DeclareFieldFormat[article]{journaltitle}{\textit{#1}}  
\DeclareFieldFormat[article]{volume}{\textit{#1}}  
\DeclareFieldFormat[article]{number}{(#1)} 
\DeclareFieldFormat[article]{pages}{#1} % Just print the page numbers as is 


\DeclareBibliographyDriver{article}
{%  
  \usebibmacro{bibindex}%  
  \printnames{author}%  
  \setunit{\labelnamepunct}\newblock  
  \printfield{year}%  
  \newunit\newblock  
  \printfield{title}%  
  \newunit\newblock  
  \printfield{journaltitle}%  
  \setunit{\addcomma\addspace}  
  \printfield{volume}%  
  \printfield{number}%  
  \setunit{\addcomma\addspace}  
  \printfield{pages}%
  \adddot%  
  \printfield{doi}%
}%  

\DeclareBibliographyDriver{book}
{%  
  \usebibmacro{bibindex}% 
  \usebibmacro{begentry}% 
  % Check if there's an editor or whether it's an Author-Editor volume
  \ifboolexpr%
  {
    not test {\ifnameundef{author}}%
    and %
    test {\ifnameundef{editor}} %
  }%
  {%
    % Author-present case  
    \printnames{author}% Print the authors' names  
    \setunit{\labelnamepunct}\newblock%  
    \printfield{year}% Print the year in parentheses 
    \setunit{\adddot\space}% 
    \iffieldundef{title}%
      {\printfield{booktitle}}% If 'title' is undefined, use 'booktitle'
      {\printfield{title}}% Otherwise use 'title'
    \setunit{\addspace}%
    \iffieldundef{edition}%  
      {}%  
      {\ifthenelse{\iffieldequalstr{edition}{1st} \OR \iffieldequalstr{edition}{1}}% Check if edition is '1st' or just '1'  
        {}% Do nothing for 1st edition  
        {\printfield{edition}\addspace}% Print edition if not first  
      }%  
    % Author & Editor-present case
    \ifboolexpr
    {%
      not test{\ifnameundef{author}}%
      and%
      not test{\ifnameundef{editor}}%
    }
    {
      \newunit\newblock%
      \printnames{editor}%
      \setunit{\addcomma\space}%
      \printfield{booktitle}%
      \space%
      \printfield{pages}%
      \newunit\newblock%
    }
    {}
  }
  {
    % Edited book or part of an edited volume  
    \printnames{editor}% Print the editor's names  
    \setunit{\addspace}%  
    % {(Ed.)}%  
    \setunit{\labelnamepunct}\newblock%  
    \printfield{year}% Print the year in parentheses  
    \newunit\newblock%  
    \printfield{booktitle}%
  } 
  % Set to ensure no line break before publisher
  %\setunit{\addspace}%
  \newunit%  
  \printlist{publisher}%  Publisher requires the command \printlist not \printfield as it is a list
  \adddot%
  \printfield{doi}%   
}

\DeclareFieldFormat[book]{year}{(#1)}
\DeclareFieldFormat[book]{title}{\textit{#1}}
\DeclareFieldFormat[book]{edition}{(#1\addspace ed.).}
\DeclareFieldFormat[book]{pages}{(pp. #1)}


\ExplSyntaxOn% This function is written using commands from the expl3 package and requires loading its own enviornment
% Declare variables
\seq_new:N \l__bibbreeze_input_seq          %Internal sequence for input items
\tl_new:N \l__bibbreeze_input_tl            %Internal token list for input string  
\tl_new:N \l__bibbreeze_item_tl             %Internal token list for current item 
\seq_new:N \l__bibbreeze_location_list_seq  %Internal sequence for location  
\int_new:N \l__bibbreeze_counter_int        %Internal integer variable as a counter
\bool_new:N \l__bibbreeze_continue_bool     %Internal boolean for main loop  
\bool_new:N \l__bibbreeze_nestedloop_bool   %Internal boolean loop for putting items in location sequence 
\tl_new:N \g_bibbreeze_date_tl              %Public token list for date  
\tl_new:N \g_bibbreeze_location_tl          %Public token list for storing location parameters
\tl_new:N \g_bibbreeze_title_tl             %Public token list for title  

% Define the macro  

%%%%%%%The algorithm for extracting field information bundeled in another field
\NewDocumentCommand{\ExtractFieldInfo}{m}
{
  \tl_set:Ne \l__bibbreeze_input_tl {#1}%Use \Ne to expand to acsses the characters of the input variable. Also use \tl_set:Ne to expand l_my_input_tl before passing to function.
  \seq_set_split:NnV \l__bibbreeze_input_seq {,} \l__bibbreeze_input_tl %Split the list into items based on commas
  \seq_log:N \l__bibbreeze_input_seq %Check the log file for output of l_my_input_seq

  \bool_set_true:N \l__bibbreeze_continue_bool
  %Set title, location and date as global tokens instead of local to acesses them outside ExtractFieldInfo
  \tl_gset:Nn \g_bibbreeze_title_tl {} 
  \tl_gset:Nn \g_bibbreeze_location_tl {}
  \tl_gset:Nn \g_bibbreeze_date_tl {}

  \bool_while_do:Nn \l__bibbreeze_continue_bool
  {
    %Get the first item in case it matches the first regex, as popping it would require insearting it again.
    \seq_get_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
    %Trim spaces in case of spaces before or after the item
    \tl_trim_spaces:N \l__bibbreeze_item_tl

    \regex_match:nVTF {.\d{4}\Z} \l__bibbreeze_item_tl
    {
      % Last item matches four digits at the end of the string
      \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
      \tl_set:Ne \l_my_parenthesized_item_tl {( \l__bibbreeze_item_tl )}
      
      % Construct title with consistent formatting
      \tl_gset:Ne \g_bibbreeze_title_tl {
        \seq_use:Nn \l__bibbreeze_input_seq {,~}
        \c_space_tl \l_my_parenthesized_item_tl
      }
      \tl_log:N \g_bibbreeze_title_tl
      \bool_set_false:N \l__bibbreeze_continue_bool % Exit loop since we've handled the year
    }
    {
      % If the last item doesn't match, we proceed with other checks
      \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
      \tl_trim_spaces:N \l__bibbreeze_item_tl

      \tl_if_eq:nVT {Proceedings} \l__bibbreeze_item_tl
      {
        % If it is Proceedings, pop the next item
        \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
        \tl_trim_spaces:N \l__bibbreeze_item_tl
      }

      \regex_match:nVTF { ^\d{4} } \l__bibbreeze_item_tl
      {
        % If it is a four-digit number, treat it as a year
        %\tl_set:Ne \l_my_date_tl {\l__bibbreeze_item_tl}
        \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
        \tl_trim_spaces:N \l__bibbreeze_item_tl
        
        % Check if the next item is a month
        \regex_match:nVT { ^(J|F|Mar|A|May|Jun|Jul|Aug|S|O|N|D) } \l__bibbreeze_item_tl % High probability of month for \l__bibbreeze_item_tl at this stage; minimal check is sufficent
        {
          \tl_gset:Ne \g_bibbreeze_date_tl {\l__bibbreeze_item_tl}
          \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
          \tl_trim_spaces:N \l__bibbreeze_item_tl
          \seq_put_left:Ne \l__bibbreeze_location_list_seq {\l__bibbreeze_item_tl}
        }
        % Determine location item count based on whether "USA" is present
        \tl_if_eq:nVTF { USA } {\l__bibbreeze_item_tl}
        {
          %If USA pop out the next two items
          \int_set:Nn \l__bibbreeze_counter_int {2}
        }
        {
          %If not USA pop out only the next item
          \int_set:Nn \l__bibbreeze_counter_int {1}
        }
        %Use another while loop for handeling the location items
        \bool_set_true:N \l__bibbreeze_nestedloop_bool
        \bool_while_do:Nn \l__bibbreeze_nestedloop_bool
        {
          \int_compare:nTF {\l__bibbreeze_counter_int > 0}
          {
            \seq_if_empty:NF \l__bibbreeze_input_seq
            {
              \seq_pop_right:NN \l__bibbreeze_input_seq \l__bibbreeze_item_tl
              \tl_log:N \l__bibbreeze_item_tl
              %Store popped locations in a new variable from left to right
              \seq_put_left:Ne \l__bibbreeze_location_list_seq {\l__bibbreeze_item_tl}
              \tl_trim_spaces:N \l__bibbreeze_item_tl
              \int_decr:N \l__bibbreeze_counter_int
            }
            %Specifically indiate that if counter hits zero, exit the loop
            \int_compare:nT {\l__bibbreeze_counter_int == 0}
            {
              \bool_set_false:N \l__bibbreeze_nestedloop_bool
            }
          }
          {
            \bool_set_false:N \l__bibbreeze_nestedloop_bool
          }
        }
        \seq_log:N \l__bibbreeze_location_list_seq
        %After extracting the location set in new variable 
        \tl_gset:Ne \g_bibbreeze_location_tl {\seq_use:Nn \l__bibbreeze_location_list_seq {,~}}

        % After handling location, check for the year again
        \seq_if_empty:NF \l__bibbreeze_input_seq
        {
          \bool_set_true:N \l__bibbreeze_continue_bool
        }
        {
          \bool_set_false:N \l__bibbreeze_continue_bool
        }
      }
      {
        % If no special conditions are met, add to title or check if we're done
        \tl_if_empty:NF \g_bibbreeze_title_tl
        {
          \tl_gput_left:Nn \g_bibbreeze_title_tl {,~} % Add comma and space only if title is not empty
        }
        %Set comma right-seperated items of title from left in g_my_title_tl
        \tl_gput_left:Ne \g_bibbreeze_title_tl {\l__bibbreeze_item_tl}
        \seq_if_empty:NTF \l__bibbreeze_input_seq
        {
          % Remove the last comma if this was the last item
          %\tl_remove_trailing:Nn \l_my_title_tl {,}
          \bool_set_false:N \l__bibbreeze_continue_bool
        }
        {
          \bool_set_true:N \l__bibbreeze_continue_bool
        }
      }
    }
  }
}
%Define new commands for making the title, location and date available for printing
\NewDocumentCommand{\PrintDatetl}{}
{
  \tl_if_empty:NF \g_bibbreeze_date_tl
    {
      \addspace
      \tl_use:N \g_bibbreeze_date_tl
      \tl_log:N \g_bibbreeze_date_tl
    }
}
\NewDocumentCommand{\PrintLocationtl}{}
{
  \tl_if_empty:NF \g_bibbreeze_location_tl
    {
      \addspace
      \ifnameundef{editor}
      {\tl_use:N \g_bibbreeze_location_tl}
      {}
      \tl_log:N \g_bibbreeze_location_tl
    }
}
\NewDocumentCommand{\PrintTitletl}{}
{
  \tl_if_empty:NF \g_bibbreeze_title_tl
    {
      \addspace
      \ifboolexpr{
        test {\ifnameundef{editor}} and test {\iffieldundef{isbn}}% The isbn is included when a proceedings paper in an edited book lacks an editor field.
      }
        {\tl_use:N \g_bibbreeze_title_tl}
        {\textit{\tl_use:N \g_bibbreeze_title_tl}}
    }
}

\cs_new_protected:Npn \ExtractURLInfo #1#2#3#4
{
  \str_set:Ne \l__bibbreeze_url_str {#1}
  \tl_log:N \l__bibbreeze_url_str
  \seq_set_split:NnV \l__bibbreeze_segments_seq {/} \l__bibbreeze_url_str
  \seq_log:N \l__bibbreeze_segments_seq
  \bool_set_false:N \l__bibbreeze_found_bool
  \seq_map_inline:Nn \l__bibbreeze_segments_seq
  {
    \regex_match:nnTF {^#2\Z} {##1}
    {
      \bool_set_true:N \l__bibbreeze_found_bool
      \tl_log:n { Found~#2~in~segment:~##1 }
      \seq_map_break:
    }
    {}
  }
  \bool_if:NTF \l__bibbreeze_found_bool
  {#3}
  {#4}
}
\ExplSyntaxOff

\DeclareFieldFormat[inproceedings]{title}{%
  \ifboolexpr{
    test {\ifnameundef{editor}} and test {\iffieldundef{isbn}}
  }
  {\textit{#1}}
  {#1}
}
\DeclareFieldFormat[inproceedings]{year}{%
  \ifboolexpr{
    test {\ifnameundef{editor}} and test {\iffieldundef{isbn}}
  }
  {(#1,\space \PrintDatetl)}
  {(#1)}
}
\DeclareFieldFormat[inproceedings]{\PrintTitletl}{%
#1
}
\NewDocumentCommand{\EditorMode}{}
{
  \hspace*{-9pt}\printnames{author}%  
  \setunit{\labelnamepunct}\newblock%  
  \printfield{year}% 
  \setunit{\labelnamepunct}\newblock% 
  \printfield{title}% 
  \setunit{\labelnamepunct}\newblock%
  \printtext{In }%
  \ifnameundef{editor}% In case edtior's field is missing.
  {%
    \printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{Find editors from publisher's source!}}
    \addspace%
  }%
  {%
    \printnames{editor}%
  }%
  \ifnumgreater{\value{editor}}{1}% If there are multiple editors print Eds., if only one editor print Ed.
  {\printtext{(Eds.),}}%
  {\printtext{(Ed.),}}%
  \PrintTitletl
  \setunit\newblock\addspace
  (\printfield{pages})\adddot%
  \addspace
  \printlist{publisher}\adddot%
  \printfield{doi}%
}
% The format of how inproceeding papers should be printed in the references
\DeclareBibliographyDriver{inproceedings}
{%
  \noindent
  \usebibmacro{bibindex}%
  \ExtractFieldInfo{\thefield{booktitle}}% Call the designed function first, to make the title (PrintTitletl), location (PrintLocationtl) and date (PrintDatetl) available
  \ifnameundef{editor}% Handles missing editor in incomplete BibTeX entries with conditional checks
  {
    \iffieldundef{biburl}
    {
      \iffieldundef{isbn}
      {\hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{Find biburl field from online source (address bar)!}}}% If a paper has neither the necessary ISBN nor biburl field, find the url online.
      {\EditorMode}% Function EditorMode already accounts for non existing editor
    }
    {
      %In case a journal article accidentally has an @inproceedings entry in bibtex. (it would be identified by "article" or "journals").
      \ExtractURLInfo{\thefield{biburl}}{article}
      {
        \hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{This paper is an article, find correct BibTeX reference!}}
      }
      {% If "article" not found, it's definetly a session
        \ExtractURLInfo{\thefield{biburl}}{journals}
        {
          \hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{This paper is an article, find correct BibTeX reference!}}
        }
        {% If "journals" not found, it's definetly a session
          \hspace*{-8pt}\printnames{author}%  
          \setunit{\labelnamepunct}\newblock%  
          \printfield{year}% 
          \setunit{\labelnamepunct}\newblock% 
          \printfield{title}% 
          \setunit{\labelnamepunct}\newblock%
          \printtext{[Paper presentation]\adddot}%
          \PrintTitletl\addcomma
          \PrintLocationtl\adddot
          \printfield{doi}%
        }%
      }%
    }%
  }
  {
    \iffieldundef{biburl}
    {
      \iffieldundef{isbn}
      {\hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{Find biburl field from online source (address bar)!}}}% If a paper has neither the necessary ISBN nor biburl field, find the url online.
      {\EditorMode}% Function EditorMode already accounts for non existing editor
    }
    {
      \ExtractURLInfo{\thefield{biburl}}{article}
      {\hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{This paper is an article, find correct BibTeX reference!}}}%
      {% If "article" not found, check for the regex "journals".
        \ExtractURLInfo{\thefield{biburl}}{journals}
        {\hspace{-5pt}\printtext{\textcolor[rgb]{0.695, 0.0, 0.0}{This paper is an article, find correct BibTeX reference!}}}%
        {\EditorMode}% If "article" and "journals" not found, the paper is definetly a proceedings and print editor mode.
      }%
    }%
  }%
}
\DeclareBibliographyAlias{mastersthesis}{thesis} % mastersthesis is recognized as a built-in type, thus can't override; use alias to thesis for custom driver formatting.

\DeclareBibliographyAlias{phdthesis}{thesis} % phdthesis is recognized as a built-in type, thus can't override; use alias to thesis for custom driver formatting.
\DeclareFieldFormat[thesis]{year}{(#1)}
\DeclareFieldFormat[thesis]{title}{\textit{#1}}
\DeclareIndexFieldFormat[thesis]{type}{(#1)}
\DeclareIndexFieldFormat[thesis]{number}{(Publication No.\space #1)}

\ExplSyntaxOn
\NewDocumentCommand \PopOneItem { m }
{
  \clist_item:en {#1} {1}
}% Function also works for a list with only one item as there's nothing to split and the item is places in l_tmpa_tl
\ExplSyntaxOff


\DeclareBibliographyDriver{thesis}
{%  
  \usebibmacro{bibindex}%  
  \printnames{author}% Print the author's name  
  \setunit*{\labelnamepunct}\newblock%  
  \printfield{year}% Print the year in parentheses  
  \newunit\newblock%  
  \printfield{title}% Print the dissertation title
  \space
  \ifthenelse{\equal{\thefield{type}}{phdthesis}} % Check if the entry type it's a PhD thesis
  {%
    [\printtext{Doctoral dissertation}\addcomma\space\printlist{institution}]% Print text alongside the institution. Also, the field institution is treated as a list. Thefore, to print it requires the command \printlist
  }
  {%
    \ifthenelse{\equal{\thefield{type}}{mathesis}}% In BibLaTeX, the type of "mastersthesis" entries is "mathesis"
      {%
        [\printtext{Master's thesis}\addcomma\space\printlist{institution}]% Print text alongside the institution
      }
      {}% Do nothing if it's neither
  }
  \PopOneItem{\thefield{bibsource}} %Call function to just print the first item of bibsource
  \newunit\newblock
  \printfield{url}%
}

\ExecuteBibliographyOptions{labeldateparts=true, sorting=nyt, maxnames=20}